BM19 寻找峰值

前置知识点补充:

二分查找的非递归模板:

复制代码
 1 //有序数组中查找某个数
 2     public static Boolean BinarySearch(int[] arr,int num)
 3     {
 4         int begin = 0, last = arr.length - 1;
 5         while (begin <= last) {
 6             int mid = begin + ((last - begin) >> 1);
 7             if (arr[mid] > num) {
 8                 last = mid - 1;
 9             }
10             else if (arr[mid] == num) {
11                 return true;
12             }
13             else {
14                 begin = mid + 1;
15             }
16         }
17         return false;
18     }
复制代码

 

题目链接:https://www.nowcoder.com/practice/fcf87540c4f347bcb4cf720b5b350c76

最开始的解题思路:

先把数组长度为1和边界的情况考虑掉,再考虑中间的情况即可。

只要考虑掉边界情况,中间的代码就可以用二分查找的模板进行套用转化实现

复制代码
 1 public int findPeakElement (int[] nums) {
 2          //此方法先处理掉长度为0,1和边界的情况
 3          if (nums == null || nums.length == 1 || nums[0] > nums[1]) return 0;
 4          if (nums[nums.length - 1] > nums[nums.length - 2]) return nums.length - 1;
 5          int begin = 0, last = nums.length - 1;
 6          //套用二分查找的模板,进行合理的转化即可
 7          while (begin <= last)
 8          {
 9              int mid = (begin + last ) / 2;
10              if (nums[mid] < nums[mid - 1])
11              {
12                  last = mid - 1;
13              }
14              else
15              {
16                  begin = mid + 1;
17              }
18          }
19          return last;
20     }
复制代码

 

 

之后在改进时遇到的一个bug(死循环情况)

复制代码
 1 //以下方法会出现死循环
 2      public static int wrongFindPeakElement(int[] nums)
 3      {
 4          int begin = 0 ,last = nums.length - 1;
 5          while (begin < last)
 6          {
 7              int mid = (begin + last) / 2;
 8              if (nums[mid] < nums[mid - 1]) //mid处不可能是峰值
 9              {
10                  last = mid - 1;          
11              }
12              else 
13              {
14                  begin = mid; //因为此处begin值不能往上涨,如果出现到begin=n,last=n+1的情况时,就会导致
15                                //mid = (n+n+1) / 2 =n,所以begin永远是n,begin永远<last,造成死循环
16                                //但如果是begin = mid + 1,last = mid的情况就不会产生以上所说的情况
17              }
18          }
19          return begin;
20      }
复制代码

 

根据分析解决后得到的最简明的一种代码(不需要分析特殊情况,把所有情况都归为了一种):

复制代码
 1 public static int findPeakElement (int[] nums) {
 2          int begin = 0 , last = nums.length - 1;
 3          while (begin < last)
 4          {
 5              int mid = (begin + last) / 2;
 6              if (nums[mid] > nums[mid + 1]) //mid处肯定不是峰值
 7              {
 8                  last = mid;
 9              }
10              else //即nums[mid] < nums[mid + 1] //mid处可能是峰值
11              {
12                  begin = mid + 1;
13              }
14          }
15          return last;
16      }
复制代码

 

 

小细节补充:如果 mid = (begin + last) / 2会溢出,可以写为 mid =  begin + (last - begin) / 2;

posted @   jue1e0  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示