因为旋转数组非全局有序,std::lower_bound要求严格升序,否则行为未定义;必须手写二分逻辑:每次取mid后,若nums[left]

旋转数组里二分查找为什么不能直接套 std::lower_bound
因为旋转排序数组不是全局有序的,std::lower_bound 要求容器严格升序,否则行为未定义——哪怕数组只转了一次(比如 [4,5,6,7,0,1,2]),直接传给它会返回错误位置甚至越界。
必须手写逻辑,在每次 mid 判断后,根据「哪一段是有序的」来收缩区间。
关键点在于:任意一次划分后,left ~ mid 和 mid ~ right 必有一段严格有序。利用这点才能安全比较、丢弃一半。
如何判断哪边有序并决定搜索方向
以 nums[left] 为条件判断左半段是否有序(注意等号,处理单元素或重复边界):
- 若成立:左半段有序 → 若
target落在[nums[left], nums[mid]]内,则right = mid - 1;否则left = mid + 1 - 否则:右半段有序 → 若
target落在[nums[mid], nums[right]]内,则left = mid + 1;否则right = mid - 1
注意:nums[mid] 每次都要和 target 对比,相等就直接返回 mid;边界更新永远用 mid ± 1,避免死循环。
示例片段(无重复元素):
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <h3>遇到重复元素时 <code>nums[left] == nums[mid]</code> 怎么办</h3>
<p>当 <code>nums[left] == nums[mid]</code>,无法确定哪边有序(比如 <code>[2,2,2,0,2,2]</code> 中,<code>left=0, mid=2</code>,值都是 2,但最小值在右边)。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img
src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a>
<p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>此时唯一安全做法是收缩左边界:<code>left++</code>,跳过这个不确定的值。虽然最坏退化到 O(n),但能保证正确性。</p>
<p>修改判断条件为:</p>
<ul>
<li>若 <code>nums[left] → 左有序</code>
</li>
<li>若 <code>nums[left] > nums[mid]</code> → 右有序</li>
<li>若 <code>nums[left] == nums[mid]</code> → <code>left++</code>,继续下一轮</li>
</ul>
<p>别试图“跳过多个”,每次只 <code>++</code> 一次,否则可能漏掉 <code>target</code>。</p>
<h3>边界和空数组这些细节容易漏掉</h3>
<p>函数开头必须检查 <code>nums.empty()</code>,否则 <code>right = -1</code> 会导致 <code>while</code> 条件异常或后续访问越界。</p>
<p><code>left</code> 和 <code>right</code> 初始化要对齐索引范围:<code>right = nums.size() - 1</code>,不是 <code>nums.size()</code>;循环条件用 <code>left ,不是 <code> —— 否则单元素数组会直接退出。</code></code></p>
<p>返回值统一用 <code>-1</code> 表示未找到,别用 <code>nums.size()</code> 或其他 magic number,和 STL 习惯一致也方便调用方处理。</p>
<p>真正麻烦的从来不是二分本身,而是旋转带来的局部有序性判断——一旦 <code>left</code>、<code>mid</code>、<code>right</code> 三个点值关系没理清,分支就容易写反。建议在纸上画两组数(含重复),手动走一遍流程再敲代码。</p></int>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










