当前位置: 首页 > news >正文

66.搜索旋转数组

面试题 10.03. 搜索旋转数组
 搜索旋转数组。给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。

示例 1:

 输入:arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 5输出:8(元素5在该数组中的索引)

 

 

 

 

核心二分逻辑  来源:乐清

预处理:判断数组是否为空,空则直接返回 

1避免空指针异常

2循环内优先检查左边界:若 arr[left] == target,直接返回 left保证找到的是最小索引

 ① 若 arr[mid] == targetright=mid(左侧可能有更小索引);
 ② 若 arr[0] < arr[mid](左半区有序):
   - 目标值在左半区 → right=mid-1
   - 否则 → left=mid+1
 ③ 若 arr[0] > arr[mid](右半区有序):

  - 目标值在右半区 → left=mid+1

  - 否则 → right=mid-1

④ 若 arr[0] == arr[mid](无法判断有序)→ left++逐步缩小查找范围,逼近目标5循环结束(left>right),返回 -1目标值不存在

2. 为什么必须优先检查 left?

如果去掉这行代码,会出现两个问题:
  • 无法保证「最小索引」:比如数组 arr = [1,0,1,1,1],target=0,若不检查 left,可能先找到 mid 位置的 1,再收缩边界,最终虽然能找到 0,但逻辑冗余;
  • 效率降低:明明已经找到最小索引,却还要继续循环,浪费计算资源。

3. 为什么要 left++

  • 「无法判断有序区间」时,无法通过 mid 收缩右边界(比如不知道目标值在左还是右);
  • arr[left] 已经检查过不等于 target(因为开头先判断了 arr[left] == target),所以可以安全地把 left 右移一位,缩小查找范围;
  • 若不 left++,会导致 leftright 永远不变,进入死循环。
class Solution {public int search(int[] arr, int target) {// 处理空数组边界情况if (arr == null || arr.length == 0) {return -1;}int n = arr.length;int left = 0;          // 左边界:初始化为数组第一个元素下标int right = n - 1;     // 右边界:初始化为数组最后一个元素下标// 二分查找核心循环:缩小查找范围,直到左边界超过右边界while (left <= right) {// 核心优化1:左边界匹配直接返回(保证找到的是最小索引)// 因为left是当前遍历到的最小候选下标,匹配则无需继续查找if (arr[left] == target) {return left;}// 计算中间下标:用 left + (right-left)/2 而非 (left+right)/2,避免整数溢出int mid = left + (right - left) / 2;// 核心逻辑1:中间值匹配目标值 → 收缩右边界到mid(左侧可能有更小索引的目标值)if (arr[mid] == target) {right = mid;}// 核心逻辑2:左半区是严格有序的(arr[0] < arr[mid])else if (arr[0] < arr[mid]) {// 目标值在左半区(有序区间)→ 收缩右边界if (arr[0] <= target && target < arr[mid]) {right = mid - 1;}// 目标值在右半区(旋转区间)→ 收缩左边界else {left = mid + 1;}}// 核心逻辑3:右半区是严格有序的(arr[0] > arr[mid])else if (arr[0] > arr[mid]) {// 目标值在右半区(有序区间)→ 收缩左边界if (arr[mid] < target && target <= arr[right]) {left = mid + 1;}// 目标值在左半区(旋转区间)→ 收缩右边界else {right = mid - 1;}}// 核心逻辑4:arr[0] == arr[mid](处理重复元素,无法判断哪半区有序)else {// 左边界右移,缩小查找范围(避免死循环)left++;}}// 循环结束未找到目标值return -1;}
}
View Code

【超级麻烦的边界,arr[left] == target 和left++想半天想不懂】

【背吧】

 

class Solution {public int search(int[] arr, int target) {List<Pair<Integer, Integer>> pairs = new ArrayList<>();for (int i = 0; i < arr.length; i++) {Pair<Integer, Integer> pair = new Pair<>(i, arr[i]);pairs.add(pair);}pairs.sort(Comparator.comparingInt(Pair::getValue));int left = 0, right = arr.length - 1;while (left < right) {int mid = (left + right) / 2;if (pairs.get(mid).getValue() >= target) {right = mid;} else {left = mid + 1;}}if (pairs.get(left).getValue() != target) return -1;return pairs.get(left).getKey();}
}
View Code
http://www.jsqmd.com/news/345993/

相关文章:

  • 教学演示首选!4K 高清录屏神器 免费汉化无广告 自带标注工具
  • 完整教程:C++继承基础:继承中的默认成员函数-静态成员变量-与友元(二)
  • 808KB 轻量王者!Gif123 免费开源 GIF 录屏神器 录编压转一站式搞定
  • Web 实现多组件同步滚动
  • 10 年经典不褪色!美明定时助手 4M 免费无广告 多任务定时超实用
  • 智能健康监测手环设计
  • 为何云卓科技C11吊舱能适配多种规格载具?
  • 智能浇花系统的设计
  • AI智能识别人脸情绪项目
  • 亲测好用! 降AIGC软件 千笔·降AI率助手 VS 学术猹,继续教育首选
  • 【开题答辩全过程】以 基于Python的茶叶销售数据可视化分析系统设计实现为例,包含答辩的问题和答案
  • 剖析黑龙江汽车噪音治理,各品牌价格与服务对比排名 - 工业品牌热点
  • leetcode 904. Fruit Into Baskets 水果成篮
  • 【开题答辩全过程】以 基于PHP的发热病人管理平台的设计与实现为例,包含答辩的问题和答案
  • 设计稿还原为什么总是出问题?一次设计转代码的实测分享
  • 2026年深圳婚姻纠纷律师联系电话推荐:可靠律师资源与沟通建议 - 品牌推荐
  • 2026年深圳离婚律师联系电话推荐:五大优选律师介绍 - 品牌推荐
  • 脚本双雄:Bash vs Python,谁才是你开发的“灵魂伴侣” ?
  • 2026年深圳婚姻纠纷律师联系电话推荐:专业律师资源全览 - 品牌推荐
  • 写作压力小了!10个降AIGC平台测评:专科生如何选才能降AI率过关?
  • 2026年成都靠谱的制袋机公司盘点,华裕托盘袋制袋机实力大揭秘 - myqiye
  • 了解迪拜房产相关资讯,时代出国成功案例多不多? - 工业设备
  • 两级电力市场环境下计及风险的省间交易商最优购电模型
  • 2026年探讨高性价比的聚氨酯筛板工厂,为您节省成本 - 工业推荐榜
  • 2026年深圳离婚纠纷律师联系电话推荐:专业团队联系指引 - 品牌推荐
  • docker拉取代理脚本
  • 靠谱的医药车间净化板漆面修复公司有哪些 - 工业品网
  • 千匠网络领跑S2B电商软件排名:重塑供应链赋能新范式 - 圆圆小达人
  • 全场景视频技术赋能千行百业:点播直播视频会议平台EasyDSS全面构建视频新生态
  • 【异常】使用 Set.of 构建集合抛出 IllegalArgumentException 异常排查