Найти наименьшее число в списке - PullRequest
0 голосов
/ 07 ноября 2018

Я написал программу на Go, которая находит наименьшее число в списке, и она работает. Однако я не очень понимаю логику. Не могли бы вы объяснить, почему это работает?

package main

import "fmt"

func main() {
    x := []int{
        48, 96, 86, 68,
        57, 82, 63, 70,
        37, 34, 83, 27,
        19, 97, 9, 17,
    }

    for i, num := range x {
        if num < i {
            fmt.Println(num)
        }
    }
}

Детская площадка: https://play.golang.org/p/Awuw2Th1g2V

Выход:

9

Решение в моем учебнике другое, и я понимаю логику там.

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

Чтобы найти наименьшее число в списке, вам нужно будет перебрать список и сохранить наименьшее число, которое вы в данный момент нашли. Сравните это «самое маленькое число» с каждым другим номером в списке, и если вы найдете меньшее, замените его наименьшее число. В конце итерации вы узнаете наименьшее число в списке.

smallest := x[0]            // set the smallest number to the first element of the list
for _, num := range x[1:] { // iterate over the rest of the list
    if num < smallest {     // if num is smaller than the current smallest number
        smallest = num      // set smallest to num
    }
}
fmt.Println(smallest)
0 голосов
/ 07 ноября 2018

Чтобы немного расширить ответ @ hoque: тот факт, что пример программы, которую вы предоставляете, является чисто случайным. Если правильное значение 9 будет первым в срезе, не будет никакого вывода вообще.

Существуют различные способы достижения цели определения наименьшего целого (есть несколько способов):

func smallestOfCopyWithSort(in []int) int {

  // Make a copy, so we do not have to modify the original slice.
  // Note: Do NOT use this approach, it is here only for completeness.
  copy := append([]int(nil), in...)
  sort.Ints(copy)
  return (copy[0])
}

func smallestWithSort(in []int) int {
  // Sort the slice.
  // Note that it will be modified and you
  // need to make sure that it will always
  // be sorted, even when you add new values.
  sort.Ints(in)
  return (in[0])
}

func smallestWithMattsApproach(in []int) int {
  smallest := in[0]            // set the smallest number to the first element of the list

  for _, num := range in[1:] { // iterate over the rest of the list
    if num < smallest { // if num is smaller than the current smallest number
      smallest = num // set smallest to num
    }
  }

  return smallest
}

@ Подход Мэтта , вероятно, является лучшим, поскольку он довольно быстрый без необходимости изменения исходного среза. И это действительно зависит от того, чего вы хотите достичь. Вот некоторые тесты

$ go test -test.benchmem -bench=. -test.cpu 1,2,4 -test.benchtime=10s
goos: darwin
goarch: amd64
pkg: <redacted>
BenchmarkSortWithCopy          5000000       345 ns/op       160 B/op          2 allocs/op
BenchmarkSortWithCopy-2        5000000       354 ns/op       160 B/op          2 allocs/op
BenchmarkSortWithCopy-4        5000000       352 ns/op       160 B/op          2 allocs/op
BenchmarkMattsApproach       100000000      15.1 ns/op         0 B/op          0 allocs/op
BenchmarkMattsApproach-2     100000000      15.1 ns/op         0 B/op          0 allocs/op
BenchmarkMattsApproach-4     100000000      15.2 ns/op         0 B/op          0 allocs/op
BenchmarkSort               2000000000      0.00 ns/op         0 B/op          0 allocs/op
BenchmarkSort-2             2000000000      0.00 ns/op         0 B/op          0 allocs/op
BenchmarkSort-4             2000000000      0.00 ns/op         0 B/op          0 allocs/op

Не удивительно, что smallestOfCopyWithSort на несколько порядков медленнее, чем другие подходы, если вызываться несколько раз.

Мэттс быстро работает и ничего не копирует и не модифицирует.

Однако, если вам нужно многократно обращаться к наименьшему количеству среза, сортировка среза (по возрастанию) и простой доступ к первому элементу более эффективны. Причина этого заключается в том, что срез будет изменен в порядке сортировки. Однако у этого подхода есть предостережение: вам нужно быть очень осторожным, когда вы добавляете значения к срезу , или прибегать к нему каждый раз, когда вы изменяете его, что может свести на нет преимущество в производительности, в зависимости от вашего соотношения. из читает и пишет в / из среза. Лично я нахожу smallestWithSort решение, которое я использую чаще всего, так как срезы, с которыми я работаю, обычно не меняются.

Заключение

Если вам нужно только получить доступ к наименьшему числу один раз или порядок значений срезов имеет значение, используйте подход Мэтта. Если порядок не имеет значения и , вам необходимо обращаться к наименьшему номеру более одного раза, вам, вероятно, следует использовать smallestWithSort, учитывая ограничения.

0 голосов
/ 07 ноября 2018

В

for i, num := range x {
        if num < i {
            fmt.Println(num)
        }
    }

Здесь i представляет индекс, а num представляет значение. Итак, ваше if условие представляет значение меньше, чем индекс, затем печатает значение. Ибо значение 9 равно 9, а индекс 14. Таким образом, он печатает 9, а это не то, что вы хотите сделать.

...