您的位置:首页 > 其它

[置顶] 发现一个数组中重复的数字,448和287的总结 ---重要

2017-02-17 13:39 274 查看
区别一、448题目没有限制不能改变原来的数组,所以采用的是交换机制,不断的将错误位置上的数据不断的交换移动到本该属于其的位置上去,则重新遍历时,nums[i]!=i+1的数字即没有出现的数字,但287题目则限制了不能改变原来的数组,所以不能采用交换机制的方法,方法类似采用查找循环链表的环入口的方法,或者可以采用利用二分查找的思想;

区别二、448题目中1-n之间重复的数字只出现了两次,但是在287中则至少出现两次

一、448题目

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

Example:

Input:

[4,3,2,7,8,2,3,1]

Output:

[5,6]

采用的方法是:不断的将错误位置上的数据不断的交换移动到本该属于其的位置上去,则重新遍历时,nums[i]!=i+1的数字即没有出现的数字

//注意不断的将错误位置上的数据不断的交换移动到本该属于其的位置上去,则重新遍历时,nums[i]!=i+1的数字即没有出现的数字
vector<int> findDisappearedNumbers(vector<int>& nums) {
int len = nums.size();
vector<int> result;

for(int i = 0; i < len; i++)
{
if(nums[i] == i+1)
{
continue;
}
else
{
while(nums[nums[i] - 1] != nums[i] )
{
//int idx = nums[i] - 1;
int temp = nums[nums[i] - 1];
nums[nums[i] - 1] = nums[i];
nums[i] = temp;
}
}

}

for(int i = 0; i < len; i++)
{
if(nums[i] != i+1)
{
result.push_back(i+1);
}
}

return result;
}


二、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 the array (assume the array is read only).

You must use only constant, O(1) extra space.

Your runtime complexity should be less than O(n2).

There is only one duplicate number in the array, but it could be repeated more than once.

二分查找:

int findDuplicate(vector<int>& nums) {
//二分查找,思想利用下标来实现,诸如:1...10的数中,如果小于5的数目大于5,那么表明重复的数字一定在小于5的数目中,妙哉
int len = nums.size();
if(len == 0 || len == 1)
return -1;

int low = 0;
int high = len - 1;
while(low <= high)
{
int mid = low + (high - low) / 2;
int count = 0;

for(int i = 0; i < len; i++)
if(nums[i] <= mid)
count++;

if(count > mid)
high = mid - 1;
else
low = mid + 1;
}

return low;
}


寻找链表环入口的方法:

int findDuplicate(vector<int>& nums) {
//像寻找单链表的环入口点的思路一样,设置一块一慢的指针,由于数组中存在重复节点,则可通过下标来联想成链表
int len = nums.size();
if(len == 1 || len == 0)
return -1;

int slow = nums[0];
int fast = nums[slow];
//以下为求两个指针第一次相遇的点
while(slow != fast)
{
slow = nums[slow];
fast = nums[nums[fast]];
}

//以下求重复元素的节点,即重复元素的入口节点
fast = 0;
while(fast != slow)
{
fast = nums[fast];
slow = nums[slow];
}

return slow;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐