zoukankan      html  css  js  c++  java
  • LeetCode Notes_#81 搜索旋转排序数组II

    LeetCode Notes_#81 搜索旋转排序数组II

    Contents

    题目

    假设按照升序排序的数组在预先未知的某个点上进行了旋转。

    ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。

    编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。

    示例 1:

    输入: nums = [2,5,6,0,0,1,2], target = 0
    输出: true
    示例 2:
    输入: nums = [2,5,6,0,0,1,2], target = 3
    输出: false
    

    进阶:
    这是 搜索旋转排序数组 的延伸题目,本题中的 nums  可能包含重复元素。
    这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?

    思路

    • 这题与33题唯一的区别在于允许数字重复,那么每次进行二分搜索的时候,就无法判断中点的左边有序还是右边有序。如果nums[start] == nums[mid],就直接忽略掉start,自增到start++重新判断。

    思路图解
    思路图解

    解答

    1. class Solution { 
    2. public boolean search(int[] nums, int target) { 
    3. int len = nums.length; 
    4. int start = 0; 
    5. int end = len - 1; 
    6. //ERROR:考虑输入为空的corner case 
    7. if (len == 0) return false; 
    8. //TIP:start,end相邻的时候,就已经可以结束了,防止再去计算mid,与start比较,会陷入死循环 
    9. while(start + 1 < end){ 
    10. //TIP:防止溢出,mid是负数 
    11. //如果数字比较大,用mid = (start + end) / 2的写法就可能会溢出 
    12. int mid = start + (end - start) / 2; 
    13. if (nums[mid] == target) return true; 
    14. if (nums[mid] == nums[start]) start++; 
    15. if (nums[mid] > nums[start]){ 
    16. //ERROR:这里不仅仅要和mid比大小,还要和start比大小 
    17. if (nums[mid] > target && nums[start] <= target) end = mid; 
    18. else start = mid; 
    19. //ERROR:这里不能直接写else,否则nums[mid]==nums[start]时,也会进入这里边,三个分支一定是互斥的 
    20. }else if(nums[mid] < nums[start]){ 
    21. //ERROR:这里不仅仅要和mid比大小,还要和end比大小 
    22. //为什么上边是和start比,这里是和end比? 
    23. //因为必须是在一个单调区间比较才有意义,这里已经确定了是在后一个单调区间,所以跟end比才有意义。start同理。 
    24. if(nums[mid] < target && nums[end] >= target) start = mid; 
    25. } 
    26. } 
    27. //TIP:由于在start和end相邻的时候已经终止循环了,所以循环结束后,要单独判定start/end 
    28. //假如start+1==end时,依然进行二分搜索,mid == start,这时就不知道target在左侧还是右侧,只能直接判断 
    29. if(nums[start] == target) return true; 
    30. if(nums[end] == target) return true;  
    31. //如果所有都执行完了,没有返回true,就是不在数组里边 
    32. return false; 
    33. } 
    34. } 

    这里在注释当中以标签的形式写了一些内容,ERROR代表我犯过的错误,TIP是技巧的总结。我发现与其单独写一段话描述代码思路,不如直接写在注释里,复习的话,直接看代码就完事了,方便。

    体会

    写笔记的目的不是为了好看,而是为了自己整理思路和回顾,所以反而随意一点(反正也不会有人看...),才能坚持下来,以前想着要把这个题解写的多么好,但是现实就是我目前还很菜,先能自己大概写一写,能进入一个刷题的良性循环才是王道,如果非要追求每题都自己搞清楚,太费时间,可能某一段时间比较闲,可以坚持住,那要是没有时间,这个习惯就会被抛弃。总的来说,要循序渐进。

  • 相关阅读:
    高精度 模板
    《图论》邻接表
    模板整理
    H
    C
    同余定理的应用(处理大数
    H
    1153: 简易版最长序列
    1152: 二分搜索
    1151: 大整数加法(正数)
  • 原文地址:https://www.cnblogs.com/Howfars/p/12001351.html
Copyright © 2011-2022 走看看