LeetCode-Cycle Detection,Find the Duplicate Number

      本来以为这题很简单,但是看要求,第一不能改变这个数组,第二只能使用O(1)的空间,第三时间复杂度小于O(n^2),就不能使用遍历数组的方式来解决了。

有两种方法,一种是利用Binary Search,一种是利用Floyd的cycle detection算法。

 Binary Search Method

    This method is based on a theroy called Pigeonhole princinpal.

    In mathematics,Pigeonhole princinpal states that if n items are put into a m container,and n>m,then at least one container must contain more than one item.

思路1:1.At first,the search space is 1~n,we find out the middle of 1~n as mid and figure out how many numbers in the array is equals or less than mid.We define it as count.

      2.If count is equals or less than mid,then the search space shrink to mid+1~n.

      3.If count is bigger than mid,then the search space shrink to 1~mid.

        e.g. Given an array,[1,2,3,4,4],n=4

    mid=1+(4-1)/2=2,then we compare all the numbers in the array and get count=2.

    There is only two numbers between 1~2,and count=2.It means that there are 2 spaces for (1~2).

    You may think that just because there are 2 spaces for 1~2,it doesn‘t mean there are no duplicate numbers between 1~2,it can be {1,1}   or {2,2} when count=2.

    But think about the rest of the array.

    There are two numbers between (1~2),so there are 3 spaces left and the rest of the numbers are between (3~4).

    There are only two numbers between 3~4 but there are 3 space for them,so according to the Pigeonhole princinpal, there must be a            duplicate number between (3~4).

    And we can know from the question that there is only one duplicate number in the array.So the duplicate one must be between (3~4).

    Then we keep on searching.mid=3+(4-3)/2=3,then we can conclude that count=3.There are 3 numbers between 1~3 and there are 2          numbers between (4~4).We may conclude that the duplicate number is 4.

  public static int findDuplicate(int[] nums) {
			int low=1;
			int high=nums.length-1;
			int count=0;
			while(low<high) {
				count=0;
				int mid=low+(high-low)/2;//先找到中间值
				for(int i=0;i<nums.length;i++) {//统计数组中小于等于这个值的有多少个
					if(nums[i]<=mid) {
						count++;
					}
				}
				if(count<=mid) {//如果个数小于等于中间值,说明low~mid之间没有重复的值,重复的值在mid+1~high中
					low=mid+1;

				} else {//如果个数大于中间值,说明low~mid中存在重复的值
					high=mid;
				}
			}
			return low;

   }

Cycle Detection Algorithm by Floyd

 How it works

  

  Let‘s have a tortoise and a hare(Two pointers) pointing to the beginning of the list.

  First part of the algorithm

  They start to move and the tortoise move a step while the hare move two steps each time.

  Then they meet at some meeting point.

  The figure illustrates a cycle and m states the step from the start to the cycle.

  The cycle length is n and the tortoise and the hare first meet at k steps away from the cycle start.

  The tortoise move i step,And i=m+p*n+k(Assume that the tortoise move around the cycle for p times).

  The hare move 2i step,And 2i=m+q*n+k(Assume that the hare move around the cycle for q times).

  i=2i-i=(q-p)*n so that m+k=(q-2p)n

  We can conclude that m+k is some multiples of the length of the cycle.

  Second part of the algorithm

  Let‘s move the tortoise to the start of the list and keep the hare at the meeting point.

   Now we start to move them and they both move a step at a time.

   The hypothesis is that if we move them at the same speed,then they will finally meet at the beginning of the cycle.

If we move them m+k steps,then the tortoise will be at the previous meeting point as we can see from the picture.

   What about the hare?Because m+k is some multiples of n,then the hare also move several cycle length and get to the meeting point.

   What if we move them m steps?

   The tortoise will be at the beginningg of the cycle,and the hare would go be k steps short of completing (q-2p) rotations.

   ince it started k steps in front of the cycle beginning, hare would have to arrive at the cycle beginning.

   Obviously m<m+k,so when they first meet,they will get to the beginning of the cycle and we get the result.

 

	public static int findDuplicate(int[] nums) {
		int fast=0;
		int slow=0;
		//算法的第一部分
		do {
			fast=nums[nums[fast]];//fast一次走两步
			slow=nums[slow];//slow一次走一步
		}while(slow!=fast);//最终他们相遇
		//算法的第二部分
		int finder=0;//finder设置到起点
		while(finder!=fast) {//当他们相遇时,他们所在的点就是cycle的起点
			finder=nums[finder];
			fast=nums[fast];
		}
		return fast;
	}

  

时间: 2024-10-21 15:07:29

LeetCode-Cycle Detection,Find the Duplicate Number的相关文章

&lt;LeetCode OJ&gt; 287. Find the Duplicate Number

287. Find the Duplicate Number My Submissions Question Total Accepted: 18097 Total Submissions: 48596 Difficulty: Hard Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate

leetcode题解之Find the Duplicate Number

1.题目描述 2.分析 利用C++的 标准模板库 set 对数组进行读取,然后插入,如果检测到元素已经在set内部,则返回该元素值即可.时间复杂度为 O(n),空间复杂度为 O(n); 3.代码 1 int findDuplicate(vector<int>& nums) { 2 std::set<int> myset; 3 std::pair< std::set<int>::iterator,bool > ret; 4 5 for( int i =

LeetCode 287. Find the Duplicate Number

Find the Duplicate Number | LeetCode OJhttps://leetcode.com/problems/find-the-duplicate-number/ 这个题目属于编码比较简单但解法分析过程比较复杂. 首先,把1~n放入0~n个元素,必定有两个或以上元素重复.数字里没有0,所以从下标0出发不会再回到最初的元素0. 假设当前的下标为x,下一步的下标为f(x),若f(x) = A[x], 也即每次跳到一个元素,则下一步移动到当前元素值对应的元素下标.我们来证明

[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

leetcode Find the Duplicate Number

题目连接 https://leetcode.com/problems/find-the-duplicate-number/ Find the Duplicate Number Description 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.

[LeetCode] 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 element must exist. Assume that there is only one duplicate number, find the duplicate one. Note: You must not modify t

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. Note: You must not modify th

LeetCode 287. Find the Duplicate Number (python 判断环,时间复杂度O(n))

LeetCode 287. Find the Duplicate Number 暴力解法 时间 O(nlog(n)),空间O(n),按题目中Note"只用O(1)的空间",照理是过不了的,但是可能判题并没有卡空间复杂度,所以也能AC. class Solution: # 基本思路为,将第一次出现的数字 def findDuplicate(self, nums: List[int]) -> int: s = set() for i in nums: a = i in s if a

[LeetCode] 287. Find the Duplicate Number(Floyd判圈算法)

传送门 Description 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. Note: You mu