План курса / Все задачи / Алгоритмы и структуры данных
Поиск дубликата
средне
Дан массив nums, содержащий n + 1 чисел, каждое из которых находится в диапазоне от 1 до n. Требуется найти число, которое повторяется более одного раза (такое число всегда одно). Нельзя модифицировать массив или использовать дополнительную память.
Пример 1:
Ввод: nums = [3,1,3,4,2]
Вывод: 3
Пример 2:
Ввод: nums = [1,1]
Вывод: 1
Пример 3:
Ввод: nums = [4,4,4,4,4,4]
Вывод: 4
Объяснение: число может иметь более 1 повтора
Ограничения:
len(nums) >= 2
1 <= nums[i] <= len(nums)
public class Solution
{
public static int FindDuplicateNum(List<int> nums)
{
// Фаза 1: найти точку пересечения
int slow = 0;
int fast = 0;
do
{
slow = nums[slow];
fast = nums[nums[fast]];
} while (slow != fast);
// Фаза 2: найти вход в цикл
slow = 0;
while (slow != fast)
{
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
}
#include <vector>
using namespace std;
int findDuplicateNum(vector<int>& nums) {
// фаза 1: найти точку пересечения
int slow = 0;
int fast = 0;
do {
slow = nums[slow];
fast = nums[nums[fast]];
} while (slow != fast);
// фаза 2: найти вход в цикл
slow = 0;
while (slow != fast) {
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
package main
func findDuplicateNum(nums []int) int {
// фаза 1: найти точку пересечения
slow := 0
fast := 0
for {
slow = nums[slow]
fast = nums[nums[fast]]
if slow == fast {
break
}
}
// фаза 2: найти вход в цикл
slow = 0
for slow != fast {
slow = nums[slow]
fast = nums[fast]
}
return slow
}
import java.util.*;
public class Solution {
public Integer findDuplicateNum(List<Integer> nums) {
// фаза 1: найти точку пересечения
int slow = 0;
int fast = 0;
do {
slow = nums.get(slow);
fast = nums.get(nums.get(fast));
} while (slow != fast);
// фаза 2: найти вход в цикл
slow = 0;
while (slow != fast) {
slow = nums.get(slow);
fast = nums.get(fast);
}
return slow;
}
}
import java.util.*;
public class Solution {
public Integer findDuplicateNum(List<Integer> nums) {
// фаза 1: найти точку пересечения
int slow = 0;
int fast = 0;
do {
slow = nums.get(slow);
fast = nums.get(nums.get(fast));
} while (slow != fast);
// фаза 2: найти вход в цикл
slow = 0;
while (slow != fast) {
slow = nums.get(slow);
fast = nums.get(fast);
}
return slow;
}
}
from typing import *
def find_duplicate_num(nums: List[int]) -> int:
# фаза 1: найти точку пересечения
slow = 0
fast = 0
while True:
slow = nums[slow]
fast = nums[nums[fast]]
if slow == fast:
break
# фаза 2: найти вход в цикл
slow = 0
while slow != fast:
slow = nums[slow]
fast = nums[fast]
return slow
Оценка сложности
Время: O(n), где n - длина массива nums
Память: O(1)
Для решения используется "Алгоритм Флойда поиска цикла". Если видишь его первый раз, то можешь поискать информацию о нем самостоятельно. В ближайшем времени мы добавим обучающее видео по этой теме.