【LeetCode每日一題】——287.尋找重複數
阿新 • • 發佈:2021-05-02
文章目錄
一【題目類別】
- 陣列
二【題目難度】
- 中等
三【題目編號】
- 287.尋找重複數
四【題目描述】
- 給定一個包含 n + 1 個整數的陣列 nums ,其數字都在 1 到 n 之間(包括 1 和 n),可知至少存在一個重複的整數。
- 假設 nums 只有 一個重複的整數 ,找出 這個重複的數 。
五【題目示例】
- 示例 1:
輸入:nums = [1,3,4,2,2]
輸出:2 - 示例 2:
輸入:nums = [3,1,3,4,2] - 示例 3:
輸入:nums = [1,1]
輸出:1 - 示例 4:
輸入:nums = [1,1,2]
輸出:1
六【題目提示】
- 2 < = n < = 3 ∗ 1 0 4 2 <= n <= 3 * 10^4 2<=n<=3∗104
- n u m s . l e n g t h = = n + 1 nums.length == n + 1 nums.length==n+1
- 1 < = n u m s [ i ] < = n 1 <= nums[i] <= n 1<=nums[i]<=n
-
n
u
m
s
中
只
有
一
個
整
數
出
現
兩
次
或
多
次
,
其
餘
整
數
均
只
出
現
一
次
nums 中 只有一個整數 出現 兩次或多次 ,其餘整數均只出現 一次
七【解題進階】
- 如 何 證 明 n u m s 中 至 少 存 在 一 個 重 復 的 數 字 ? 如何證明 nums 中至少存在一個重複的數字? 如何證明nums中至少存在一個重復的數字?
- 你 可 以 在 不 修 改 數 組 n u m s 的 情 況 下 解 決 這 個 問 題 嗎 ? 你可以在不修改陣列 nums 的情況下解決這個問題嗎? 你可以在不修改數組nums的情況下解決這個問題嗎?
-
你
可
以
只
用
常
量
級
O
(
1
)
的
額
外
空
間
解
決
這
個
問
題
嗎
?
你可以只用常量級 O(1) 的額外空間解決這個問題嗎?
- 你 可 以 設 計 一 個 時 間 復 雜 度 小 於 O ( n 2 ) 的 解 決 方 案 嗎 ? 你可以設計一個時間複雜度小於 O(n^2) 的解決方案嗎? 你可以設計一個時間復雜度小於O(n2)的解決方案嗎?
八【解題思路】
- 使用快慢指標,慢指標走一步,快指標走兩步,問題抽象為判斷是否有環,陣列中的值抽象為連結串列的next指標,如果有的話返回入環點的值。假設從頭到入環點的距離為n,入環點到快慢指標第一次相遇的距離為m,第一次相遇的位置到入環點的距離為l,環的周長為s,可以推出m==n,那麼只要在第一次相遇時,把快指標移動到頭位置,速度變為1,和慢指標一起移動,最後肯定在入環點相遇,返回即可
九【時間頻度】
- 時間複雜度: O ( N ) O(N) O(N)
十【程式碼實現】
- Java語言版
package Array;
public class p287_FindTheDuplicateNumber {
public static void main(String[] args) {
int[] nums = {1, 3, 4, 2, 2};
int res = findDuplicate(nums);
System.out.println("res = " + res);
}
public static int findDuplicate(int[] nums) {
// 宣告一個快指標和一個慢指標,從同一出發點,快指標每次走兩步,慢指標每次走一步
int fast = 0;
int slow = 0;
while (true) {
fast = nums[nums[fast]];
slow = nums[slow];
// 如果存在環的話,此時快慢指標會相遇
if (slow == fast) {
// 相遇之後,慢指標回到出發點,接下來快慢指標兩個一起走,再次相遇之處就是環形的入口
slow = 0;
while (nums[slow] != nums[fast]) {
slow = nums[slow];
fast = nums[fast];
}
return nums[slow];
}
}
}
}
- C語言版
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
int findDuplicate(int* nums, int numsSize)
{
/*宣告一個快指標和一個慢指標,從同一出發點,快指標每次走兩步,慢指標每次走一步*/
int fast = 0;
int slow = 0;
while (true)
{
fast = nums[nums[fast]];
slow = nums[slow];
/*如果存在環的話,此時快慢指標會相遇*/
if (fast == slow)
{
/*相遇之後,慢指標回到出發點,接下來快慢指標兩個一起走,再次相遇之處就是環形的入口*/
slow = 0;
while (nums[slow] != nums[fast])
{
slow = nums[slow];
fast = nums[fast];
}
return nums[slow];
}
}
}
/*主函式省略*/
十一【提交結果】
- Java語言版
- C語言版