这4个题都是针对旋转的排序数组。其中153、154是在旋转的排序数组中找最小值,33、81是在旋转的排序数组中找一个固定的值。且153和33都是没有重复数值的数组,154、81都是针对各自问题的版本1增加了有重复数值的限制条件。
153、154都需要考虑是否旋转成和原数组一样的情况,特别的,154题还需要考虑10111和11101这种特殊情况无法使用二分查找。
33、81则不用考虑这些情况。
找最小值的题主要是利用最小值小于他前一个位置的数,同时也小于后一个位置的数
start是前面升序的最后一个,end是后面升序的第一个, 只剩两个时,end就代表了那个最小值
153. Find Minimum in Rotated Sorted Array
class Solution { public: int findMin(vector<int>& nums) { int start = 0; int end = nums.size() - 1; int mid; if(nums[start] < nums[end]) return nums[start]; while(start + 1 < end){ mid = start + (end - start)/2; if(nums[mid] < nums[start]) end = mid; else start = mid; } return nums[end]; } };
154. Find Minimum in Rotated Sorted Array II
class Solution { public: int findMin(vector<int>& nums) { int start = 0; int end = nums.size() - 1; int mid = start + (end - start)/2; if(nums[start] < nums[end]) return nums[start]; if(nums[start] == nums[end] && nums[start] == nums[mid]){ int min_num = INT_MAX; for(int i = 0;i < nums.size();i++){ if(nums[i] < min_num) min_num = nums[i]; } return min_num; } while(start + 1 < end){ mid = start + (end - start)/2; if(nums[mid] < nums[start]) end = mid; else start = mid; } return nums[end]; } };
33. Search in Rotated Sorted Array
这个题和剑指上旋转数组求最小值有点不一样,还是用二分查找的方法做,但条件判断较为繁琐。首先明确一点,无论怎么分,左右两侧总有一个是有序的,并且一般情况左侧是大的数,右侧是小的数。mid小于target的时候,相当于要找一个更大的数,所以想法是先排除一般情况下小的数,如果start < mid,证明这是个升序,那只可能在右侧;如果start > mid,证明右侧是升序,只要和最大的比较,也就是end,如果比end小,说明数字在右侧,如果比end大,说明数字在左侧,因为比最大的都大了。
总体上就是当target大于mid的时候,就去比较可能出现大数的左侧区间,如果是升序,那就能排除;如果左侧区间不是升序,则右侧是升序,需要拿这个升序的最大值和mid进行比较来确定下一个区间
class Solution { public: int search(vector<int>& nums, int target) { if(nums.empty()) return -1; int start = 0; int end = nums.size() - 1; int mid; while(start + 1 < end){ mid = start + (end - start)/2; if(nums[mid] == target) return mid; else if(nums[mid] < nums[end]){ if(nums[mid] < target && nums[end] >= target) start = mid; else end = mid; } else{ if(nums[mid] > target && nums[start] <= target) end = mid; else start = mid; } } if(nums[start] == target) return start; if(nums[end] == target) return end; return -1; } };
自己的写法:
其实是可以使用mid - 1,mid+1的,因为之前做了nums[mid] == target的判断,这说明mid不可能等于target,所以可以去掉。
最需要注意的是,在判断单调区间时,start、end与target的比较一定是<=或者>=,必须考虑边界相等的情况
总体的思路就是:判断单调区间,然后判断target属于不属于这个区间,属于就在这个区间找,不属于就去另一个区间找。判断属于不属于,就是拿target与这个区间的边界进行判断。
class Solution { public: int search(vector<int>& nums, int target) { if(nums.empty()) return -1; int start = 0,end = nums.size() - 1; while(start + 1 < end){ int mid = start + (end - start)/2; if(nums[mid] == target) return mid; else if(nums[start] < nums[mid]){ if(target < nums[mid] && nums[start] <= target) end = mid - 1; else start = mid + 1; } else{ if(target > nums[mid] && nums[end] >= target) start = mid + 1; else end = mid - 1; } } if(nums[start] == target) return start; if(nums[end] == target) return end; return -1; } };
81. Search in Rotated Sorted Array II
这个题与Search in Rotated Sorted Array不同在于,这个题里面可能包含重复的数字。
代码上的区别主要是在进行单调区间判断的时候,即如果start或者end与mid的值相等的情况要单独列出来,列出来的方式是start++,mid--
Search in Rotated Sorted Array直接else其实是包括了=这种情况,但是因为本身数组不存在相等的,所以忽略了这个问题。
class Solution { public: bool search(vector<int>& nums, int target) { if(nums.empty()) return false; int start = 0; int end = nums.size() - 1; int mid; while(start + 1 < end){ mid = start + (end - start)/2; if(nums[mid] == target) return true; else if(nums[mid] < nums[end]){ if(nums[mid] < target && nums[end] >= target) start = mid; else end = mid; } else if(nums[mid] > nums[end]){ if(nums[mid] > target && nums[start] <= target) end = mid; else start = mid; } else end--; } if(nums[start] == target) return true; if(nums[end] == target) return true; return false; } };
http://www.cnblogs.com/grandyang/p/4325840.html
704. Binary Search
class Solution { public: int search(vector<int>& nums, int target) { if(nums.empty()) return -1; int start = 0; int end = nums.size() - 1; int mid; while(start + 1 < end){ mid = start + (end - start)/2; if(nums[mid] == target) return mid; else if(nums[mid] < target) start = mid; else end = mid; } if(nums[start] == target) return start; if(nums[end] == target) return end; return -1; } };