[Leetcode] 旋转问题(旋转数组的查找,旋转list,旋转矩阵)
2015-08-16 11:29
525 查看
[1] Search in Rotated Sorted Array
在二分查找问题当中,对于边界的查找,尤其是==的情况应该放到左边界上,因为对于mid的求取又是就是left,所以这是检测应该是true,所以下面的nums[mid]>=nums[left],如果改为nums[mid]>nums[left]就会出现问题。
假设按照上面的错误思路改为
具体问题是如何发生的,我们举个例子
[3 1] 1
left =0 ,right=1, mid=0, 红色部分判断为false, 所以right part is sorted
这是判断 target没有在有序的部分,所以 right--;
那么之后就永远找不到1了。
[2] Search in Rotated Sorted Array II
参考
遇到这个问题,显然问题的难点是在相同元素的干扰上,如果直接去想如何处理这些复杂的问题,可能会陷入非常复杂的思维误区。我们可以从上面的针对没有重复元素的情况进行简单的改进。
由于这时又重复元素,所以if(nums[mid]>=nums[left]){//left part is sorted这条语句失效,因为会遇到下面的情况
1 2 1 1 1,中间的1等于左边的1,所以认为左边是有序的,但是这里并不是这种情况,在第一个问题当中出现这种情况的原因是mid和left是相等的情形,在这里不仅如此。
所以需要对这个问题进行分解.分等于和不等于两种情况,显然不等于的时候,原来的假设仍然是成立的。
[3] Find Minimum in Rotated Sorted Array
参考
6,7,8,9,1,2,3,4,5
我们维持两个指针,left 指向左边的递增数组,right指向右边的递增数组,通过不断地向中间移动两个指针,最后left指向左边递增数组的最后一个元素,right指向右边递增数组的第一个元素。
最后的判停条件式right-left==1.
int nums[size];int left=0,right=size-1;
int mid=0;
while(nums[left]>nums[right]){
//如果不对right-left==1这个条件进行判断,可能会出现特殊的情况
if(right-left==1) {
mid=right;
return right;
}
int mid = (left+right)/2;
if(nums[mid]>nums[left]) left=mid;//左半边是sorted,最小元素一定在右边,切中间元素在右边
else right=mid;//右半边是sorted,最小元素一定在左边,且中间元素在左边
}
return mid;
[4] Find Minimum in Rotated Sorted Array II
参考
同样的道理,这时由于相同元素的出现,上面的判断将会失效。
比如 2 2 2 2 1 或者 2 1 2 2 2
会判定最小元素在左边,实际上是错误的。
[5] Rotate Array
1 2 3 4 5 6 7 -> 4 5 6 7 1 2 3
1. 3 2 1 7 6 5 4
2. 4 5 6 7 1 2 3
[6] Rotate List
在相应位置截断
[7] Rotate Image
首先上下翻转,然后绕主对角线翻转
在二分查找问题当中,对于边界的查找,尤其是==的情况应该放到左边界上,因为对于mid的求取又是就是left,所以这是检测应该是true,所以下面的nums[mid]>=nums[left],如果改为nums[mid]>nums[left]就会出现问题。
public class Solution { public int search(int[] nums, int target) { int left =0,right = nums.length-1; while(left<=right){ int mid = left + (right-left)/2; if(nums[mid]==target) return mid; if(nums[mid]>=nums[left]){//left part is sorted if(nums[left]<=target&&target<nums[mid]) right=mid-1; else left=mid+1; }else{//right part is sorted if(nums[mid]<target&&target<=nums[right]) left=mid+1; else right=mid-1; } } return -1; } }
假设按照上面的错误思路改为
public class Solution { public int search(int[] nums, int target) { int left =0,right = nums.length-1; while(left<=right){ int mid = left + (right-left)/2; if(nums[mid]==target) return mid; if(nums[mid]>nums[left]){//left part is sorted if(nums[left]<=target&&target<nums[mid]) right=mid-1; else left=mid+1; }else{//right part is sorted if(nums[mid]<target&&target<=nums[right]) left=mid+1; else right=mid-1; } } return -1; } }
具体问题是如何发生的,我们举个例子
[3 1] 1
left =0 ,right=1, mid=0, 红色部分判断为false, 所以right part is sorted
这是判断 target没有在有序的部分,所以 right--;
那么之后就永远找不到1了。
[2] Search in Rotated Sorted Array II
参考
遇到这个问题,显然问题的难点是在相同元素的干扰上,如果直接去想如何处理这些复杂的问题,可能会陷入非常复杂的思维误区。我们可以从上面的针对没有重复元素的情况进行简单的改进。
由于这时又重复元素,所以if(nums[mid]>=nums[left]){//left part is sorted这条语句失效,因为会遇到下面的情况
1 2 1 1 1,中间的1等于左边的1,所以认为左边是有序的,但是这里并不是这种情况,在第一个问题当中出现这种情况的原因是mid和left是相等的情形,在这里不仅如此。
所以需要对这个问题进行分解.分等于和不等于两种情况,显然不等于的时候,原来的假设仍然是成立的。
public class Solution { public static boolean search(int[] A, int target) { int left=0,right=A.length-1; while(left<=right){ int mid =(right+left)/2; if(A[mid]==target) return true; if(A[mid] < A[right]){// right part is sorted if(target>A[mid]&&A[right]>=target){ left=mid+1; }else{ right=mid-1; } }else if(A[mid] > A[right]){//left part is sorted if(target>=A[left]&&A[mid]>target){ right=mid-1; }else{ left=mid+1; } }else{ 20 if(A[left]!=target) left++; 21 if(A[right]!=target) right--; 22 } } return false; } }
[3] Find Minimum in Rotated Sorted Array
参考
6,7,8,9,1,2,3,4,5
我们维持两个指针,left 指向左边的递增数组,right指向右边的递增数组,通过不断地向中间移动两个指针,最后left指向左边递增数组的最后一个元素,right指向右边递增数组的第一个元素。
最后的判停条件式right-left==1.
int nums[size];int left=0,right=size-1;
int mid=0;
while(nums[left]>nums[right]){
//如果不对right-left==1这个条件进行判断,可能会出现特殊的情况
if(right-left==1) {
mid=right;
return right;
}
int mid = (left+right)/2;
if(nums[mid]>nums[left]) left=mid;//左半边是sorted,最小元素一定在右边,切中间元素在右边
else right=mid;//右半边是sorted,最小元素一定在左边,且中间元素在左边
}
return mid;
[4] Find Minimum in Rotated Sorted Array II
参考
同样的道理,这时由于相同元素的出现,上面的判断将会失效。
比如 2 2 2 2 1 或者 2 1 2 2 2
会判定最小元素在左边,实际上是错误的。
public static int findMin(int [] num) { int left = 0,right = num.length - 1; int mid = 0; //当while循环的条件不满足的时候,实际上当前的数组应该是有序的数组了 //如果刚开始就是有序的,那么放回mid=0的值就可以 //否则在while循环loop当中总会保持两者一个在右边的有序数组当中,另一个在左边的有序数组当中 while(num[left] >= num[right]){ // 分界点 if(right - left == 1){ mid = right; break; }//if mid = left + (right - left) / 2; //为下面的情况,那么无法判断中间mid在那一方,所以直接linear search if(num[left] == num[right] && num[left] == num[mid]){ return linearsearch(num,left,right); } if(num[mid] >= num[left]){ left = mid; } else{ right = mid; } } return num[mid]; }
[5] Rotate Array
1 2 3 4 5 6 7 -> 4 5 6 7 1 2 3
1. 3 2 1 7 6 5 4
2. 4 5 6 7 1 2 3
[6] Rotate List
在相应位置截断
[7] Rotate Image
首先上下翻转,然后绕主对角线翻转
相关文章推荐
- [ACM] n划分数m部分,它要求每一个部分,并采取了最大的产品(间隔DP)
- 初学Java多线程:从线程返回数据的两种方法
- uva 12545 Bits Equalizer
- C语言基础学习——第1天(类型+操作符)
- 钱币兑换问题
- 将tomcat添加到服务中
- CBLAS的安装与使用
- 队列的实现
- Spring4.x整合Quartz2.x 动态修改定时器时间(修正多定时器SpringBean异常)
- linux学习之路(1)
- scala学习之:List的map、flatMap、foreach、filter的操作代码实战
- oracle中的赋权
- Android启动页
- eclipse:No resource found that matches the given name 'Theme.AppCompat.Light'
- 砝码称重
- C语言实现字符串的左旋转
- [clone]Java中的深拷贝和浅拷贝 实例解析
- 快速判断一个数字是否是素数
- BGP相关资料
- xcode 各种项目设置