zoukankan      html  css  js  c++  java
  • 【leetcode】287. 寻找重复数

    题目链接:传送门

    题目描述:

    给定一个数组 nums 包含 n + 1 个整数,每个整数在 1 到 n 之间,包括 1 和 n。现在假设数组中存在一个重复的数字,找到该重复的数字。

    注意

    1. 不能修改数组元素,假设数组是只读的。
    2. 仅可以使用常数即O(1)O(1)的额外空间。
    3. 时间复杂度需要低于O(n2)O(n2)。
    4. 数组中仅有一个重复数字,但它可能重复超过1次。

    样例

    Example 1:

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

    Output: 2

    Example 2:

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


    算法
    (双指针移动) O(n)
    因为每个数都是 1 到 n,所以此题可以当做Linked List Cycle II来处理。
    首先first和second指针均为0,然后first每次前进一格,second每次前进两格。i前进一格在这里指的是nums[i]。剩余部分请参考Linked List Cycle II中的算法证明。
    时间复杂度
    参见Linked List Cycle II时间复杂度部分,整个数组仅遍历常数次,故时间复杂度为O(n)。

    作者:wzc1995
    链接:https://www.acwing.com/solution/LeetCode/content/302/


    将数组转化为链表形式:数组 [1,3,4,2,2]

    current / index

    0

    1 2 3 4

    next / num[index]

    1 3 4 2 2

    index为当前值的索引,num[index]为下个一值的索引next index。上表中的数组表示成链表如下图,方框中为index, num[index]

     

    利用【142_环形链表 II】的方法,找到环入口,即为重复数字

    设:

      slow指针移动速度为1,fast指针移动速度为2;slow指针在环内移动(非环部分)长度为a,slow指针在环内移动长度为b

      两指针相遇时候,slow指针移动距离为a+b,fast指针移动距离为2(a+b),可知两指针距离差a+b即为整数倍的环长

      从head移动a的距离为入环点;由2可知从head开始移动a+(a+b)的距离也为入环点,即将A点继续移动距离a则可到达入环点

      将slow指针移动回head,同时同速移动两个指针,相遇点即为入环点

    说明:

      因为数组中不含0,所以不会因为index = 0, num[0] = 0导致死循环;对于其他位置index = num[index],若该值重复则会自身成环,若无重复则不会被遍历到

    作者:LuoRong1994
    链接:https://leetcode-cn.com/problems/two-sum/solution/287_xun-zhao-zhong-fu-shu-by-user9081a/


     1 class Solution {
     2 public:
     3     int findDuplicate(vector<int>& nums) {
     4         int cnt = 0 ; 
     5         int L = 1 , R = nums.size() - 1 , Mid , ans = 0 ;
     6         while ( L < R ) {
     7             Mid = (L+R) >> 1; 
     8             cnt = 0 ;
     9             for ( int x : nums ) 
    10                 cnt +=  L <= x && x <= Mid ; 
    11             if ( Mid - L + 1 < cnt ){
    12                 R = Mid ;
    13             }else {
    14                 L = Mid + 1 ;
    15             }
    16         }
    17         return R ;
    18             
    19     }
    20 };
    二分做法
     1 class Solution {
     2 public:
     3     int findDuplicate(vector<int>& nums) {
     4         int Fir , Sec ;
     5         Fir = Sec = 0 ; 
     6         do{
     7             Fir = nums[Fir] ; 
     8             Sec = nums[nums[Sec]] ; 
     9         }while ( Fir != Sec );
    10         
    11         Fir = 0; 
    12         while ( Fir != Sec ){
    13             Fir = nums[Fir] ;
    14             Sec = nums[Sec] ; 
    15         }
    16         return Fir;
    17     }
    18 };
    双指针



  • 相关阅读:
    android 回调的理解(结合接口)
    Android Bundle、Handler和Message类介绍
    Android: Intent实现活动之间的交互
    Condition实现一个生产者一个消费者
    condition实现通知部分线程
    Condition实现等待、通知
    ReentrantLock简单实现2
    ReentrantLock的简单使用
    线程通信-基于字符流管道
    线程通信-基于字节流管道
  • 原文地址:https://www.cnblogs.com/Osea/p/11182305.html
Copyright © 2011-2022 走看看