Задачи на слайсы
1) Что выведет данная программа и почему?
Программа выведет следующие значения:
Давайте разберемся, почему так происходит:
arr1 := [...]int{1, 2, 3, 4, 5}
создает массивarr1
с пятью элементами.arr2 := arr1[:4]
создает срезarr2
, который ссылается на первые четыре элемента массиваarr1
. То естьarr2
это[1, 2, 3, 4]
.arr3 := append(arr2[:2], 9, 8, 7)
берет срез первых двух элементов изarr2
(то есть[1, 2]
), и добавляет к нему элементы9, 8, 7
. Важно отметить, чтоappend
может изменять исходный массив, если в нем достаточно места для новых элементов.В данном случае, начало слайса
arr2
ссылается на начало массиваarr1
, поэтому изменения вarr2
отражаются наarr1
.После выполнения
append
,arr3
становится[1, 2, 9, 8, 7]
,arr2
изменяется на[1, 2, 9, 8]
, (7ка не влазит, так как слайсarr2
имеет фиксированную длину в 4 элемента), аarr1
теперь[1, 2, 9, 8, 7] (так как в нем достаточно места и для 7ки)
.Вывод
fmt.Println(arr3)
,fmt.Println(arr2)
,fmt.Println(arr1)
показывает измененные значения массивов и срезов после операций сappend
.
Это пример того, как операции с срезами и функцией append
могут влиять на исходные массивы в Go, особенно когда срезы создаются на основе этих массивов.
2) Что выведет данная программа и почему?
3) Что будет выведено без аппенд и потом с ним?
Давайте разберем, что произойдет в коде с и без использования append
.
Код без использования append
append
Объяснение:
В функции
main
создается срезsl
с элементами[1, 2, 3, 4]
.Срез
sl
передается в функциюmod
.В функции
mod
происходит итерация по срезуa
(который является ссылкой наsl
), и каждый элемент заменяется на5
.После выполнения функции
mod
, срезsl
вmain
будет изменен на[5, 5, 5, 5]
, так как срезы в Go передаются по ссылке.
Вывод:
Код с использованием append
append
Объяснение:
В функции
main
создается срезsl
с элементами[1, 2, 3, 4]
.Срез
sl
передается в функциюmod
.В функции
mod
выполняетсяappend(a, 125)
, что создает новый срез, который является копиейa
с добавленным элементом125
. Этот новый срез присваивается переменнойa
внутри функцииmod
.Затем происходит итерация по новому срезу
a
, и каждый элемент заменяется на5
. Однако это изменение не влияет на исходный срезsl
, так какa
теперь указывает на новый срез.После выполнения функции
mod
, срезsl
вmain
останется неизменным, так как изменения были сделаны в копии среза.
Вывод:
Заключение
Без использования
append
: Срезsl
будет изменен на[5, 5, 5, 5]
, так как изменения происходят непосредственно в переданном срезе.С использованием
append
: Срезsl
останется неизменным[1, 2, 3, 4]
, так какappend
создает новый срез, и изменения происходят в этом новом срезе, а не в исходном.
4) Написать функцию, которая на вход принимает 2 отсортированных слайса с типом Int в ответ выдает 1 отсортированный слайс, содержащий данные из входящих слайсов. Оценить сложность алгоритма.
Для объединения двух отсортированных слайсов в один отсортированный слайс можно использовать алгоритм слияния, который является частью алгоритма сортировки слиянием (merge sort). Этот алгоритм работает за линейное время, то есть его временная сложность составляет O(n + m), где n и m — размеры входных слайсов.
Реализация функции на Go
Объяснение алгоритма
Инициализация:
Создаем результирующий слайс
result
с начальной емкостью, равной сумме длин входных слайсовa
иb
.Инициализируем индексы
i
иj
для итерации по слайсамa
иb
соответственно.
Основной цикл слияния:
Пока оба индекса
i
иj
находятся в пределах длин своих слайсов, сравниваем текущие элементыa[i]
иb[j]
.Добавляем меньший элемент в результирующий слайс и увеличиваем соответствующий индекс.
Добавление оставшихся элементов:
После завершения основного цикла, один из слайсов может содержать оставшиеся элементы. Добавляем их в результирующий слайс.
Оценка сложности
Временная сложность: O(n + m), где n и m — размеры входных слайсов. Это обусловлено тем, что каждый элемент из обоих слайсов обрабатывается ровно один раз.
Пространственная сложность: O(n + m), так как создается новый слайс, содержащий все элементы из входных слайсов.
Этот алгоритм является оптимальным для задачи слияния двух отсортированных слайсов и работает эффективно даже для больших входных данных.
5) Что выведет данная программа и почему?
Давайте разберем, что происходит в этой программе и что она выведет.
Разбор кода
Создание и заполнение слайса
x
:После этих операций
x
будет содержать[0, 1, 2]
.Создание слайсов
y
иz
:Здесь начинается интересное. Важно понимать, что
append
может изменять базовый массив слайса, если его емкость позволяет. Если емкость недостаточна,append
создаст новый массив и скопирует в него данные.y := append(x, 3)
добавляет3
кx
, так чтоy
становится[0, 1, 2, 3]
.z := append(x, 4)
добавляет4
кx
, так чтоz
становится[0, 1, 2, 4]
.
Однако, так как
x
иy
ссылаются на один и тот же базовый массив, изменениеx
черезappend
может повлиять наy
.
Вывод программы
Когда мы вызываем fmt.Println(y, z)
, мы получаем:
Почему так происходит?
Когда
y := append(x, 3)
выполняется,y
ссылается на тот же базовый массив, что иx
, но с дополнительным элементом3
.Когда
z := append(x, 4)
выполняется,z
также ссылается на тот же базовый массив, что иx
, но с дополнительным элементом4
.
Так как x
и y
ссылаются на один и тот же базовый массив, изменение x
через append
влияет на y
. В результате, оба слайса y
и z
содержат [0, 1, 2, 4]
.
Заключение
Программа выводит [0 1 2 4] [0 1 2 4]
из-за того, что append
изменяет базовый массив слайса, если его емкость позволяет. В данном случае, x
, y
и z
ссылаются на один и тот же базовый массив, что приводит к такому результату.
6) Задача: Требуется реализовать функцию uniqRandn, которая генерирует слайс длины n уникальных рандомных чисел:
Для реализации функции uniqRandn
, которая генерирует слайс длины n
уникальных случайных чисел, можно использовать несколько подходов. Один из них — это использование карты (map) для отслеживания уже сгенерированных чисел, чтобы избежать дубликатов.
Реализация функции uniqRandn
uniqRandn
Импорт необходимых пакетов:
math/rand
для генерации случайных чисел.time
для инициализации генератора случайных чисел.
Инициализация генератора случайных чисел:
Используем текущее время в наносекундах для инициализации генератора случайных чисел.
Использование карты для отслеживания уникальных чисел:
Генерируем случайные числа и добавляем их в карту до тех пор, пока не наберем нужное количество уникальных чисел.
Код
Объяснение кода
Инициализация генератора случайных чисел:
Это гарантирует, что генератор случайных чисел будет инициализирован текущим временем, что делает последовательность случайных чисел уникальной при каждом запуске программы.
Создание карты и слайса:
Карта
nums
используется для отслеживания уникальных чисел, а слайсresult
для хранения результата.Генерация уникальных случайных чисел:
Цикл продолжается до тех пор, пока количество уникальных чисел в карте
nums
не достигнетn
. Внутри цикла генерируется случайное числоnum
. Если это число еще не присутствует в картеnums
, оно добавляется в карту и слайсresult
.
Заключение
Этот код генерирует слайс длины n
уникальных случайных чисел. Если требуется другой диапазон случайных чисел, можно изменить аргумент функции rand.Intn
. Например, для генерации чисел в диапазоне от 0 до 999, используйте rand.Intn(1000)
.
Last updated