理解二分查找问题中的范围问题
Posted
技术标签:
【中文标题】理解二分查找问题中的范围问题【英文标题】:Understanding the range issue in binary seach problem 【发布时间】:2020-12-02 09:11:45 【问题描述】:编辑: 添加有关代码背后逻辑的更多详细信息。 感谢@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
应该从零开始,我想。此外,在cntRange
中,您似乎使用start
作为值(与nums[i]
相比),它实际上是nums
的索引。
@500-InternalServerError,开始和结束只是数字的范围,不是索引。我之所以把start设置为1,是因为原来的问题中,数字在[1,n]的范围内,所以start应该是1。你可以看到我尝试将start改为0来解决范围为 [0, n-1] 的问题。
【参考方案1】:
您提到的 2 个案例的问题是:
start = mid + 1;
mid 的值永远不会变为负数,因此在第一次到达这条线之后 start 的最小值永远不会小于 1。这意味着在进行二分搜索时,您永远不会看到索引 0 处的值。
【讨论】:
以上是关于理解二分查找问题中的范围问题的主要内容,如果未能解决你的问题,请参考以下文章