我正在调试以下问题并发布我正在调试和处理的解决方案,解决方案或类似的问题发布在几个论坛上,但我认为解决方案有一个错误,当num [0] = 0或一般数字[x] = x?我对么?如果我错了,请随时纠正我。
给定包含n + 1个整数的数组nums,其中每个整数在1和n之间(包括1和n),证明必须存在至少一个重复的数字。假设只有一个重复的数字,找到重复的数字。
注意: 您不能修改数组(假设该数组是只读的)。 您必须仅使用常量O(1)额外空间。 您的运行时复杂度应小于O(n2)。 数组中只有一个重复的数字,但它可以重复多次。
int findDuplicate3(vector<int>& nums)
{
if (nums.size() > 1)
{
int slow = nums[0];
int fast = nums[nums[0]];
while (slow != fast)
{
slow = nums[slow];
fast = nums[nums[fast]];
}
fast = 0;
while (fast != slow)
{
fast = nums[fast];
slow = nums[slow];
}
return slow;
}
return -1;
}
答案 0 :(得分:7)
以下是我的代码,它使用 Floyd的循环查找算法:
#include <iostream>
#include <vector>
using namespace std;
int findDup(vector<int>&arr){
int len = arr.size();
if(len>1){
int slow = arr[0];
int fast = arr[arr[0]];
while(slow!=fast){
slow = arr[slow];
fast = arr[arr[fast]];
}
fast = 0;
while(slow!=fast){
slow = arr[slow];
fast = arr[fast];
}
return slow;
}
return -1;
}
int main() {
vector<int>v = {1,2,2,3,4};
cout<<findDup(v)<<endl;
return 0;
}
注释这是有效的,因为不允许使用零,因此数组的第一个元素不是循环的一部分,因此我们找到的第一个循环的第一个元素都被引用循环内外。如果允许零,如果arr [0]处于循环中,则会失败。例如,[0,1,1]。
答案 1 :(得分:3)
从1到N = $("#header_menuId li").on('mouseover',function(){
$(this).animate({
height: '+=150px',
width: '+=150px'
});
}).on('mouseout',function(){
$(this).animate({
height: '-=150px',
width: '-=150px'
});
的整数之和。您可以使用它来查找重复 - 对数组中的整数求和,然后从总和中减去上面的公式。这是副本。
更新:上述解决方案基于(可能无效)假设输入数组由1到N的值加上单个副本组成。
答案 2 :(得分:1)
由于您无法使用任何额外空间,因此将排除使用其他哈希表。
现在,对现有阵列进行散列处理,如果允许我们修改阵列就可以实现。
ALGO:
1)从第一个元素开始。
2)散列第一个元素并对hash的值应用转换。让我们说这个转换正在产生值-ve。
3)继续下一个元素。散列元素并在应用转换之前,检查是否已经应用了转换。
4)如果是,则元素是重复的。
代码:
for(i = 0; i < size; i++)
{
if(arr[abs(arr[i])] > 0)
arr[abs(arr[i])] = -arr[abs(arr[i])];
else
cout<< abs(arr[i]) <<endl;
}
这种转换是必需的,因为如果我们要使用散列方法,则必须存在冲突才能对相同的密钥进行散列。
我无法想到一种可以在没有任何额外空间且不修改数组的情况下使用散列的方法。
答案 3 :(得分:1)