1. 程式人生 > 其它 >【LeetCode每日一題】——287.尋找重複數

【LeetCode每日一題】——287.尋找重複數

文章目錄

一【題目類別】

  • 陣列

二【題目難度】

  • 中等

三【題目編號】

  • 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
  • 示例 3:
    輸入:nums = [1,1]
    輸出:1
  • 示例 4:
    輸入:nums = [1,1,2]
    輸出:1

六【題目提示】

  • 2 < = n < = 3 ∗ 1 0 4 2 <= n <= 3 * 10^4 2<=n<=3104
  • 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 中 只有一個整數 出現 兩次或多次 ,其餘整數均只出現 一次
    nums

七【解題進階】

  • 如 何 證 明 n u m s 中 至 少 存 在 一 個 重 復 的 數 字 ? 如何證明 nums 中至少存在一個重複的數字? nums?
  • 你 可 以 在 不 修 改 數 組 n u m s 的 情 況 下 解 決 這 個 問 題 嗎 ? 你可以在不修改陣列 nums 的情況下解決這個問題嗎? nums
  • 你 可 以 只 用 常 量 級 O ( 1 ) 的 額 外 空 間 解 決 這 個 問 題 嗎 ? 你可以只用常量級 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)

十【程式碼實現】

  1. 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];
            }
        }
    }

}
  1. 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];
		}
	}
}

/*主函式省略*/

十一【提交結果】

  1. Java語言版
    在這裡插入圖片描述
  2. C語言版
    在這裡插入圖片描述