总结放前面:
BS 找 Rotated sorted array 的题目目前接触到的共四道: 33, 81, 153, 154. 两道找find target, 两道find min. 其中各包含一道no duplicate 一道contain duplicates.
重点如下:
1. 主体思路:
大框架与经典BS题目相同, find target 的题目用classic经典方法[while(left <= right)], find min用改版方法[while(left + 1 < right) + post process].
2. 针对Rotated做出的改变:
因为是rotated sorted array, 所以多数情况 left<-->mid 和 mid<-->right 这两段中, 有一段是顺序的,一段不是. [if (nums[left] < nums[mid])]. (后面再讨论全顺序的情况)
针对这种情况的处理方法是, 把不好判断的部分全部丢到else里面去!
举例:
while (left <= right) { mid = left + (right - left) / 2; if (nums[mid] == target) return mid; else if (nums[mid] < nums[right]) { if (nums[mid] < target && target <= nums[right]) { left = mid + 1; } else { right = mid - 1; } } else { if (nums[left] <= target && target < nums[mid]) { right = mid - 1; } else { left = mid + 1; } } }
LT33, rotated sorted array, find target, no duplicate.
这段代码中, 将经典的classic方法做了加工, 在判断target和nums[left]/nums[right]之前多了一步[else if (num[mid] < nums[right])].
通过这个来判断当前iter中, 哪半边儿是sorted, 哪半边儿不是.
然后在sorted的那半边儿! 进行进一步判断[if (nums[left] <= target && target < nums[mid])]. 判断target在不在sorted的这半边儿中, 这一步相当于将新问题转化成我们熟悉的问题. 到这里有细心的小伙伴就要问了, target不在这个范围中该怎么办呢?
不要慌张!!
对于out of our control的部分! 全部甩到else里就够了[奸笑]
以上就是rotated sorted array的灵魂(soul~~~~)
BTW, find min的那道题更简单, 连target都没有, 就套用这个思路洒洒水就出来了.
3. 针对duplicates做出的变化:
对于duplicates的情况, 说穿了就是比no duplicate的情况多了两个判断:
else if (nums[left] == nums[mid]) left++;
else if (nums[mid == nums[right]) right--; <--
就这么简简单单 (🎵只是简简单单的爱过, 我~还~是~我~)
4. 追加考虑rotated的情况中出现unrotated的情况(mmp……)
LeetCode 154, 需要在最前面考虑nums[left] < nums[mid] < nums[right]的情况 (别问我为什么鬼知道…反正不加这一句就不accepted……)
5. Note:
这类题应先判断mid<-->right这段, 然后把left<-->mid这段放在else中.
好了以上就是这四道题的所有思路, 下面是各道题的野原新之助ver 答案, 仅供参考.
LeetCode 33.
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
KEY WORDS: [Rotated sorted array] [find target] [no duplicate]
public int search(int[] nums, int target) { if (nums == null || nums.length == 0) return -1; int left = 0; int right = nums.length - 1; int mid = 0; while (left <= right) { mid = left + (right - left) / 2; if (nums[mid] == target) return mid; else if (nums[mid] < nums[right]) { if (nums[mid] < target && target <= nums[right]) { left = mid + 1; } else { right = mid - 1; } } else { if (nums[left] <= target && target < nums[mid]) { right = mid - 1; } else { left = mid + 1; } } } return -1; }
LeetCode 81:
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Write a function to determine if a given target is in the array.
The array may contain duplicates.
KEY WORDS: [Rotated sorted array] [find target] [contain duplicates]
public boolean search(int[] nums, int target) { if (nums == null || nums.length == 0) return false; int left = 0; int right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) { return true; } else if (nums[left] < nums[mid]) { if (nums[left] <= target && target < nums[mid]) { right = mid - 1; } else { left = mid + 1; } } else if (nums[mid] < nums[right]) { if (nums[mid] < target && target <= nums[right]) { left = mid + 1; } else { right = mid - 1; } } else if (nums[left] == nums[mid]){ left++; } else { right--; } } return false; }
LeetCode 153:
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.
You may assume no duplicate exists in the array.
KEY WORDS: [Rotated sorted array] [find min] [no duplicates]
public int findMin(int[] nums) { if (nums == null || nums.length == 0) return -1; int left = 0; int right = nums.length - 1; while (left < right - 1) { int mid = left + (right - left) / 2; if (nums[mid] < nums[right]) { right = mid; } else { left = mid; } } if (nums[left] < nums[right]) { return nums[left]; } else { return nums[right]; } }
LeetCode 154:
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.
The array may contain duplicates.
KEY WORDS: [Rotated sorted array] [find min] [contains duplicates]
public int findMin(int[] nums) { if (nums == null || nums.length == 0) { return -1; } int left = 0; int right = nums.length - 1; int mid = 0; while (left < right - 1) { mid = left + (right - left) / 2; if (nums[left] < nums[mid] && nums[mid] < nums[right]) { right = mid; } else if (nums[mid] == nums[right]) { right--; } else if (nums[left] == nums[mid] ) { left++; } else if (nums[left] < nums[mid]) { left = mid; } else { right = mid; } } if (nums[left] < nums[right]) { return nums[left]; } else { return nums[right]; } }