zoukankan      html  css  js  c++  java
  • [LeetCode] 287. Find the Duplicate Number

    Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

    Example 1:

    Input: [1,3,4,2,2]
    Output: 2
    

    Example 2:

    Input: [3,1,3,4,2]
    Output: 3

    Note:

    1. You must not modify the array (assume the array is read only).
    2. You must use only constant, O(1) extra space.
    3. Your runtime complexity should be less than O(n2).
    4. There is only one duplicate number in the array, but it could be repeated more than once.

    题意是在一个数组中找到重复的数字。数组包含N + 1个数字,数字在1 <= x <= n之间。两种解法。

    1. 二分法。注意数组是无序的。当得到数组长度len和数组长度的一半mid之后,用count记录有多少个数小于等于中间数mid。举个例子,如果数组长度是10,mid则是5,这里mid指的是数组长度的一半。如果小于mid的个数大于数组的一半,说明重复的数字一定是小于mid的;反之如果大于mid的个数过半,重复的数字一定是大于mid的。用二分法逐渐逼近这个值,注意return的是start。

    时间O(nlogn)

    空间O(1)

    Java实现

     1 class Solution {
     2     public int findDuplicate(int[] nums) {
     3         int min = 0;
     4         int max = nums.length - 1;
     5         while (min <= max) {
     6             int mid = min + (max - min) / 2;
     7             int count = 0;
     8             for (int i = 0; i < nums.length; i++) {
     9                 if (nums[i] <= mid) {
    10                     count++;
    11                 }
    12             }
    13             if (count > mid) {
    14                 max = mid - 1;
    15             } else {
    16                 min = mid + 1;
    17             }
    18         }
    19         return min;
    20     }
    21 }

    JavaScript实现

     1 /**
     2  * @param {number[]} nums
     3  * @return {number}
     4  */
     5 var findDuplicate = function(nums) {
     6     let start = 1;
     7     let end = nums.length - 1;
     8     while (start < end) {
     9         let middle = Math.floor((start + end) / 2);
    10         let count = 0;
    11         // 计算总数组中有多少个数小于等于中间数
    12         for (let i = 0; i < nums.length; i++) {
    13             if (nums[i] <= middle) {
    14                 count++;
    15             }
    16         }
    17 
    18         if (count <= middle) {
    19             start = middle + 1;
    20         } else {
    21             end = middle;
    22         }
    23     }
    24     return start;
    25 };

    2. 快慢指针。因为数组一定是有重复数字出现的所以可以用快慢指针的思路做。当快慢指针相遇之后,再走第二遍,找到重复的数字。

    时间O(n)

    空间O(1)

    Java实现

     1 class Solution {
     2     public int findDuplicate(int[] nums) {
     3         int len = nums.length;
     4         if (len > 1) {
     5             int slow = nums[0];
     6             int fast = nums[nums[0]];
     7             while (slow != fast) {
     8                 slow = nums[slow];
     9                 fast = nums[nums[fast]];
    10             }
    11             slow = 0;
    12             while (slow != fast) {
    13                 slow = nums[slow];
    14                 fast = nums[fast];
    15             }
    16             return slow;
    17         }
    18         return -1;
    19     }
    20 }

    JavaScript实现

     1 /**
     2  * @param {number[]} nums
     3  * @return {number}
     4  */
     5 var findDuplicate = function(nums) {
     6     const len = nums.length;
     7     if (len > 0) {
     8         let slow = nums[0];
     9         let fast = nums[nums[0]];
    10         while (slow !== fast) {
    11             slow = nums[slow];
    12             fast = nums[nums[fast]];
    13         }
    14         slow = 0;
    15         while (slow !== fast) {
    16             slow = nums[slow];
    17             fast = nums[fast];
    18         }
    19         return slow;
    20     }
    21     return -1;
    22 };

    LeetCode 题目总结

  • 相关阅读:
    wcf技术博客
    MFC程序崩溃的友好处理
    DESCryptoServiceProvider 类
    AttributeUsage AttributeTargets
    Word 2007第n级编号不自动按照父级标题自动编号 的解决办法
    suo的作用
    "在唯一密钥属性“name”设置为“Application”时,无法添加类型为“add”的重复集合项"
    PMP考试中的成本管理英文缩写及其含义
    删除右键新建菜单中的多余项
    使用命令行启动服务
  • 原文地址:https://www.cnblogs.com/cnoodle/p/11723719.html
Copyright © 2011-2022 走看看