Интервью: головоломка
Перейти в игру:
Учитывая массив, начинайте с первого элемента и добирайтесь до последнего, прыгая. Длина скачка может быть не больше значения в текущей позиции в массиве. Оптимальный результат - когда вы достигаете цели в минимальном количестве прыжков.
Что такое алгоритм для нахождения оптимального результата?
Пример: заданный массив A = {2,3,1,1,4} возможные пути достижения конца (индексный список)
- 0,2,3,4 (переход 2 к индексу 2, затем переход 1 к индексу 3, затем 1 к индексу 4)
- 0,1,4 (переход 1 к индексу 1, затем переход 3 к индексу 4)
Поскольку второе решение имеет всего 2 прыжка, это оптимальный результат.
Ответы
Ответ 1
Обзор
Учитывая ваш массив a
и индекс вашей текущей позиции i
, повторите следующее, пока не достигнете последнего элемента.
Рассмотрим все кандидаты "прыгающие элементы" в a[i+1]
до a[a[i] + i]
. Для каждого такого элемента с индексом e
вычислите v
= a[e]
+ e
. Если одним из элементов является последний элемент, перейдите к последнему элементу. В противном случае перейдите к элементу с максимальным v
.
Проще говоря, из элементов, находящихся в пределах досягаемости, найдите тот, который даст вам самый дальнейший следующий прыжок. Мы знаем этот выбор, x
, является правильным, потому что по сравнению с любым другим элементом y
, с которым вы можете перейти, элементы, доступные из y
, являются подмножеством элементов, достижимых из x
(за исключением элементов из обратный прыжок, который, очевидно, является плохим выбором).
Этот алгоритм работает в O (n), потому что каждый элемент нужно рассматривать только один раз (элементы, которые можно было бы считать второй раз, можно пропустить).
Пример
Рассмотрим массив значений a
, указывает, i
и суммы индекса и значения v
.
i -> 0 1 2 3 4 5 6 7 8 9 10 11 12
a -> [4, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
v -> 4 12 3 4 5 6 7 8 9 10 11 12 13
Начните с индекса 0 и рассмотрите следующие 4 элемента. Найдите одно с максимальным v
. Этот элемент находится в индексе 1, поэтому переходим к 1. Теперь рассмотрим следующие 11 элементов. Цель находится в пределах досягаемости, поэтому переходите к цели.
Demo
Смотрите здесь или здесь с кодом.
Ответ 2
Динамическое программирование.
Представьте, что у вас есть массив B
, где B[i]
показывает минимальное количество шагов, необходимых для достижения индекса i
в вашем массиве A
. Ваш ответ, конечно, находится в B[n]
, данный A
имеет n
элементы и индексы начинаются с 1. Предположим, что C[i]=j
означает, что вы перескочили из индекса j в индекс я (это нужно, чтобы восстановить путь, принятый позже)
Итак, алгоритм следующий:
set B[i] to infinity for all i
B[1] = 0; <-- zero steps to reach B[1]
for i = 1 to n-1 <-- Each step updates possible jumps from A[i]
for j = 1 to A[i] <-- Possible jump sizes are 1, 2, ..., A[i]
if i+j > n <-- Array boundary check
break
if B[i+j] > B[i]+1 <-- If this path to B[i+j] was shorter than previous
B[i+j] = B[i]+1 <-- Keep the shortest path value
C[i+j] = i <-- Keep the path itself
Количество необходимых прыжков - B[n]
. Путь, который необходимо выполнить, следующий:
1 -> C[1] -> C[C[1]] -> C[C[C[1]]] -> ... -> n
Который может быть восстановлен простым циклом.
Алгоритм имеет O(min(k,n)*n)
временную сложность и O(n)
пространственную сложность. n
- количество элементов в A
, а k
- максимальное значение внутри массива.
Примечание
Я сохраняю этот ответ, но жадный алгоритм жадности правильный и эффективный.
Ответ 3
Построить ориентированный граф из массива. например: i- > j, если | i-j | <= x [i] (В принципе, если вы можете перейти от я к j в одном прыжке, i- > j в качестве ребра на графике). Теперь найдите самый короткий путь от первого node до последнего.
FWIW, вы можете использовать алгоритм Дейкстра, чтобы найти самый короткий маршрут. Сложность - O (| E | + | V | log | V |). Поскольку | E | < п ^ 2, это становится О (п ^ 2).
Ответ 4
начните с левого (конечного).. и пройдете до номера так же, как индекс, используйте максимум таких чисел. пример, если список
list: 2738|4|6927
index: 0123|4|5678
как только вы получите этот повтор выше шага от этого номера, пока вы не достигнете крайнего правого.
273846927
000001234
если вы не найдете то, что соответствует индексу, используйте цифру с самым большим индексом и значением, большим, чем индекс. в этом случае 7. (потому что довольно скоро индекс будет больше, чем число, вы можете просто рассчитывать на 9 индексов)
Ответ 5
Основная идея:
начните строить путь от конца до начала, найдя все элементы массива, из которых можно сделать последний переход к целевому элементу (все i
такие, что A[i] >= target - i
).
рассматривать каждый такой i
как новую цель и найти путь к ней (рекурсивно).
выберите найденный путь минимальной длины, добавьте target
, return.
простой пример в python:
ls1 = [2,3,1,1,4]
ls2 = [4,11,1,1,1,1,1,1,1,1,1,1,1]
# finds the shortest path in ls to the target index tgti
def find_path(ls,tgti):
# if the target is the first element in the array, return it index.
if tgti<= 0:
return [0]
# for each 0 <= i < tgti, if it it possible to reach
# tgti from i (ls[i] <= >= tgti-i) then find the path to i
sub_paths = [find_path(ls,i) for i in range(tgti-1,-1,-1) if ls[i] >= tgti-i]
# find the minimum length path in sub_paths
min_res = sub_paths[0]
for p in sub_paths:
if len(p) < len(min_res):
min_res = p
# add current target to the chosen path
min_res.append(tgti)
return min_res
print find_path(ls1,len(ls1)-1)
print find_path(ls2,len(ls2)-1)
>>>[0, 1, 4]
>>>[0, 1, 12]