F_G

许多问题需要说清楚就可以&&走永远比跑来的重要

导航

[Leetcode] 旋转问题(旋转数组的查找,旋转list,旋转矩阵)

[1] Search in Rotated Sorted Array

在二分查找问题当中,对于边界的查找,尤其是==的情况应该放到左边界上,因为对于mid的求取又是就是left,所以这是检测应该是true,所以下面的nums[mid]>=nums[left],如果改为nums[mid]>nums[left]就会出现问题。

 1 public class Solution {
 2     public int search(int[] nums, int target) {
 3         int left =0,right = nums.length-1;
 4         while(left<=right){
 5             int mid = left + (right-left)/2;
 6             if(nums[mid]==target) return mid;
 7             if(nums[mid]>=nums[left]){//left part is sorted
 8                 if(nums[left]<=target&&target<nums[mid]) right=mid-1;
 9                 else left=mid+1;
10             }else{//right part is sorted
11                 if(nums[mid]<target&&target<=nums[right]) left=mid+1;
12                 else right=mid-1;
13             }
14         }
15         return -1;
16     }
17 }

假设按照上面的错误思路改为

 1 public class Solution {
 2     public int search(int[] nums, int target) {
 3         int left =0,right = nums.length-1;
 4         while(left<=right){
 5             int mid = left + (right-left)/2;
 6             if(nums[mid]==target) return mid;
 7             if(nums[mid]>nums[left]){//left part is sorted
 8                 if(nums[left]<=target&&target<nums[mid]) right=mid-1;
 9                 else left=mid+1;
10             }else{//right part is sorted
11                 if(nums[mid]<target&&target<=nums[right]) left=mid+1;
12                 else right=mid-1;
13             }
14         }
15         return -1;
16     }
17 }

具体问题是如何发生的,我们举个例子

[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是相等的情形,在这里不仅如此。

所以需要对这个问题进行分解.分等于和不等于两种情况,显然不等于的时候,原来的假设仍然是成立的。

 1 public class Solution {
 2     public static boolean search(int[] A, int target) {
 3         int left=0,right=A.length-1;
 4         while(left<=right){
 5             int mid =(right+left)/2;
 6             if(A[mid]==target) return true;
 7             if(A[mid] < A[right]){// right part is sorted
 8                 if(target>A[mid]&&A[right]>=target){
 9                     left=mid+1;
10                 }else{
11                     right=mid-1;
12                 }
13             }else if(A[mid] > A[right]){//left part is sorted
14                 if(target>=A[left]&&A[mid]>target){
15                     right=mid-1;
16                 }else{
17                     left=mid+1;
18                 }
19             }else{
20                 if(A[left]!=target) left++;
21                 if(A[right]!=target) right--;
22             }
23         }
24         return false;
25     }
26 }

 

[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

会判定最小元素在左边,实际上是错误的。

 1     public static int findMin(int [] num) {
 2         int left = 0,right = num.length - 1;
 3         int mid = 0;
 4         //当while循环的条件不满足的时候,实际上当前的数组应该是有序的数组了
 5         //如果刚开始就是有序的,那么放回mid=0的值就可以
 6         //否则在while循环loop当中总会保持两者一个在右边的有序数组当中,另一个在左边的有序数组当中
 7         while(num[left] >= num[right]){
 8             // 分界点
 9             if(right - left == 1){
10                 mid = right;
11                 break;
12             }//if
13             mid = left + (right - left) / 2;
14             
15             //为下面的情况,那么无法判断中间mid在那一方,所以直接linear search
16             if(num[left] == num[right] && num[left] == num[mid]){
17                 return linearsearch(num,left,right);
18             }
19             if(num[mid] >= num[left]){
20                 left = mid;
21             }
22             else{
23                 right = mid;
24             }
25         }
26         return num[mid];
27     }

 

[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

首先上下翻转,然后绕主对角线翻转

posted on 2015-08-16 11:29  F_G  阅读(484)  评论(0编辑  收藏  举报