二分法经典模版
int start;
int end;
while(start<=end)
{
int mid = (end-start1)>>2 + start;
//最终结果
if(start==end){ return start}
//结果前一段
if() { end = mid;)
//结果在后一段
else{ start = mid+1)
}
#include <iostream>
using namespace std;
/*
不修改输入,查找数组中的重复数字
len n+1 数字1~n,共10种
方法1:
创建辅助数组a[n+1]
遍历原数组,假设第i个为m
则a[m] = m
若a[m]中已经有数字,则表示m是重复的数字
*/
/*
方法2:
类似二分法
把1~n值的数组从中间分为两段
一段1~m,一段m+1~n
若1~m中有重复的,则1~m总数>m
若1~m中没有重复,则总数为m
若1~m总数>1,则继续二分,循环判断,直到 段长度==1
*/
int countRegist(const int* nums, int length, int start, int end)
{
if (nums == nullptr) return 0;
int count = 0;
for (int i = 0; i < length; i++)
{
if (nums[i] <= end && nums[i] >= start)
{
count++;
}
}
return count;
}
bool judgeNum(int nums[], int length, int& num)
{
//边界1
if (length < 0|| nums==nullptr)
{
num = -1;
return false;
}
//边界2
for (int i = 0; i < length; i++)
{
if (nums[i] < 1 || nums[i] >= length)
{
num = -1;
return false;
}
}
//开始查找重复
//找出1~n的中位数,存入m
//即分成 1~m, 和 m+1~n两段
int start = 1;
int end = length - 1;
while (start <= end)
{
//二分中间
int mid = ((end - start) >> 1) + start;
//统计1~m总共有多少个
int count = countRegist(nums, length, start, mid);
//循环到最终的结果 start ==end 即 start~start有>=2个
if (start == end)
{
if (count > 1)
{
num = start;
return true;
}
else break;
}
if (count > (mid - start + 1))
{
//start~mid-1 (值)中有重复值
end = mid;
}
else
{
//mid~end(值) 中有重复数字
start = mid + 1;
}
}
return false;
}
int main()
{
int nums[] = { 2,3,5,4,3,2,6,7 };
int length = 8;
int res = 0;
judgeNum(nums, length, res);
cout << res << endl;
system("pause");
return 0;
}