c++ - 理解二元搜索问题中的范围问题
问题描述
编辑:
添加有关代码背后逻辑的更多详细信息。感谢@Stef。
我正在尝试在 LeetCode ( https://leetcode.com/problems/find-the-duplicate-number/ ) 中解决算法问题。
下面是我解决这个问题的方法,它使用了二分搜索思想。
代码的基本逻辑是,我试图使用二进制搜索在 [1, n] 范围内找到重复的数字。
例如,如果我要在列表 [1, 3, 4, 2, 2] 中找到重复的 num。
首先,计算[1, 4]的中点,因为起点是1,终点是4,所以中点是2。然后我用cntRange函数计算列表中有多少个数字在[ 1, 2]。如果数字的数量(我们有 1、2、2、3 个数字)超过了应有的数量(应该是 2),我们通过将端点设置为中点来缩小范围并继续二进制搜索,直到完成搜索我们返回起点的现值,也就是复制的起点。
class Solution {
public:
int findRepeatNumber(vector<int> &nums) {
// special case we return -1
if (nums.size() < 2) {
return -1;
}
// binary search to cnt the numbers in certain range
int start = 1;
int end = nums.size() - 1;
while (end >= start) {
int mid = ((end - start) >> 1) + start;
int cnt = cntRange(nums, start, mid);
if (end == start) {
if (cnt > 1) {
return start;
} else {
break;
}
}
if (cnt > (mid - start + 1))
end = mid;
else
start = mid + 1;
}
return -1;
}
int cntRange(vector<int> &nums, int start, int end) {
int cnt = 0;
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] >= start && nums[i] <= end)
cnt++;
}
return cnt;
}
};
这个方法传入了 LeetCode,但是我很好奇 [1, n] 的范围,如果范围是 [0, n-1] 呢?
我尝试了两个测试集:一个是 [0, 1, 2, 0, 4, 5, 6]
另一个是 [2, 3, 1, 0, 2, 5, 3]
他们都失败了,所以我回去到我的代码尝试解决这个问题。
我将 start int 初始化为 0,并将 cnt 比较条件
从 cnt > (mid - start + 1) 更改为 cnt > (mid - start)。
但是在这种情况下,只有第一个测试通过了,我仍然无法通过第二个测试。
我仍然认为这个问题出现在cnt比较过程中,但不知道如何解决这个问题。
有人可以帮我吗?
解决方案
您提到的两种情况的问题是:
start = mid + 1;
mid 的值永远不会变为负数,因此在第一次到达这条线之后 start 的最小值永远不会小于 1。这意味着在进行二进制搜索时,您永远不会看到索引 0 处的值。
推荐阅读
- bison - 如何获得标记的野牛语法规则
- c# - 为什么要使用 ClassCleanup?
- php - LinkedIn API:尝试在组中发帖时请求正文中存在未经许可的字段
- javascript - 1&&2&&3 返回 3. 谁能解释一下原因
- c# - 使用 Newtonsoft Json 序列化循环引用
- css - 如何集中一组 div,让最后一个向左对齐?
- java - 如何在 Eclipse 插件中以编程方式执行“Debug As”->“Maven Build”?
- android - 反应原生admob任务:app:processDebugManifest FAILED错误运行
- google-docs - 如何使用 Google Docs API 添加页眉/页脚
- sql - SQL Server中的条件连接左右部分等于以防万一