LC162.寻找峰值

原题链接
image.png

思路

  • 此题极好的体现了“二分查找的关键在于二段性,而不是有序性”
  • 如果nums[i] < nums[i + 1],说明峰值必不可能在左边,因此放弃掉左边(left = mid + 1),因此本题的二段性体现在“峰值必不可能在哪一侧”。
  • 二分的细节处理
    1. 如果向上取整 ```cpp int mid = (left + right + 1) / 2;

如果放弃掉左边

left = mid;

如果放弃掉右边

right = mid - 1;

判断趋势

if (nums[i - 1] < nums[i]);

错误的写法:向上取整禁止出现 + 1

if (nums[i] < nums[i + 1]);

  1. 2. 如果向下取整
  2. ```cpp
  3. int mid = (left + right) / 2;
  4. # 如果放弃左边
  5. left = mid + 1;
  6. # 如果放弃右边
  7. right = mid;
  8. # 判断趋势
  9. if (nums[i - 1] < nums[i]);
  10. # 错误的写法:向下取整禁止出现 - 1
  11. if (nums[i] < nums[i + 1]

代码

  1. class Solution {
  2. public:
  3. int findPeakElement(vector<int>& nums) {
  4. int len = nums.size();
  5. if (!len || len == 1) return 0;
  6. // 方法一:
  7. int l = 0, r = len - 1;
  8. while (l < r) {
  9. int mid = (l + r + 1) / 2;
  10. // nums[mid + 1]可能会爆掉
  11. if (nums[mid - 1] <= nums[mid]) {
  12. // 放弃掉左边
  13. l = mid;
  14. } else {
  15. // 放弃掉右边
  16. r = mid - 1;
  17. }
  18. }
  19. // 方法二:
  20. /*
  21. int l = 0, r = len - 1;
  22. while (l < r) {
  23. int mid = (l + r) / 2;
  24. if (nums[mid] < nums[mid + 1]) {
  25. // 放弃掉左边
  26. l = mid + 1;
  27. } else {
  28. // 放弃掉右边
  29. r = mid;
  30. }
  31. }
  32. */
  33. return l;
  34. }
  35. };