Leetcode 287. Find the Duplicate Number

33 篇文章 0 订阅
30 篇文章 0 订阅

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

tag: array, binary search, two pointers

method 1 sort

method 2 set

method 3 环检测算法(Floyd’s Tortoise and Hare)

这是链表环中的快慢指针迁移运用过来的算法,因为要找重复的数,并且不运用辅助的空间,那就是环检测算法。只是数组的环检测算法跟链表的环不一样,数组的环是由索引i和对应的值nums[i]构成的环, nums[i]作为下一步的i,因为有两个索引它们对应的值重复,所以构成了环

环检测算法的解释可看:https://blog.csdn.net/xyzxiaoxiong/article/details/78761940作了详细的解释
phase1 tortoise即第一次相遇点
phase2 因为在h点第一次相遇,而为什么b=F在链接中也解释的很清楚,虽然这个公式不是太准确,但可以由小及大

第一个循环就是hare一次走两步,tortoise一次走一步,那么在有环的情况下,他们迟早相遇,tortoise即为相遇点
第二个循环,令ptr1为头指针,令ptr2为相遇的几点,因为b=F那么,那么他们每次走一步,那么将在入口节点相遇

public int findDuplicate(int[] nums) {
    // Find the intersection point of the two runners.
    int tortoise = nums[0];
    int hare = nums[0];
    do {
        tortoise = nums[tortoise];
        hare = nums[nums[hare]];
    } while (tortoise != hare);

    // Find the "entrance" to the cycle.
    int ptr1 = nums[0];
    int ptr2 = tortoise;
    while (ptr1 != ptr2) {
        ptr1 = nums[ptr1];
        ptr2 = nums[ptr2];
    }

    return ptr1;
}

method 4 Binary Search

使用鸽笼原理,当数组内的数<= mid的个数多余mid时,将search范围放在mid~high,
当个数小于等于mid时,将search范围放在low~mid,最后返回low/high(指的是索引)
巧妙的运用二分法
如n=10,mid=5,如果数组内小于等于5的个数多余5个,那么根据鸽笼原理,重复的数必在1~5内

public int findDuplicate2(int[] nums) {
    int low = 1, high = nums.length - 1;
    while (low < high) {
        int mid = (low + high) / 2;
        int count = 0;

        for (int num : nums) {
            if (num <= mid) count++;
        }

        if (count <= mid) {
            low = mid + 1;
        } else {
            high = mid;
        }
    }

    return high;
}

Summary:

  1. 环检测算法构建环,找重复
  2. 二分法和鸽笼原理的结合
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值