您的位置:首页 > 其它

[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]就会出现问题。

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

首先上下翻转,然后绕主对角线翻转
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: