// 面试题3(一):找出数组中重复的数字
// 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的。
// 请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2, 3, 1, 0, 2, 5, 3},
// 那么对应的输出是重复的数字2或者3。
static bool get_duplicate_num1(std::vector<uint32_t>& arr, uint32_t& out_data)
{
if(arr.size()<2)
{
return false;
}
auto length = arr.size();
for(auto& d:arr)
{
if(d > length - 1)
{
return false;
}
}
for(uint32_t i = 0; i < length; ++i)
{
while(arr[i] != i)
{
if(arr[i] == arr[arr[i]])
{
out_data = arr[i];
return true;
}
// 交换numbers[i]和numbers[numbers[i]]
auto temp = arr[i];
arr[i] = arr[temp];
arr[temp] = temp;
}
}
return false;
}
// 面试题3(二):不修改数组找出重复的数字
// 题目:在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至
// 少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。
// 例如,如果输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7},那么对应的
// 输出是重复的数字2或者3。
static bool get_duplicate_num2(const std::vector<uint32_t>& arr, uint32_t& out_data)
{
if(arr.size()<2)
{
return false;
}
auto length = arr.size();
for(auto& d:arr)
{
if(d > length - 1 || 0 == d)
{
return false;
}
}
uint32_t start = 1;
uint32_t end = length - 1;
while(end >= start)
{
auto middle = ((end + start) >> 1);
auto count = _count(arr, start, middle);
if(end == start)
{
if(count > 1)
{
out_data = start;
return true;
}
else
break;
}
if(count > (middle - start + 1))
{
end = middle;
}
else
{
start = middle + 1;
}
}
return false;
}
static uint32_t _count(const std::vector<uint32_t>& arr, uint32_t start, uint32_t end)
{
uint32_t count = 0;
for(auto& d:arr)
{
if(d >= start && d <= end)
{
++count;
}
}
return count;
}