280 Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] <= nums[3]....

Example:

Input: nums = [3,5,2,1,6,4]
Output: One possible answer is [3,5,1,6,2,4]

280要求的是可以大于等于,其实简单。

方法一:
1. 先排序,得到序列 a0<=a1<=a2<=a3<=a4....<ai<=ai+1
2. 然后从a1 开始,交换相邻的, 这样就会有a0<=a2>=a1<=a4>=a3<=an
class Solution {
    public void wiggleSort(int[] nums) {
       
        Arrays.sort(nums);
        
        for(int i=1; i<nums.length-1; i+=2){
            swap(nums, i,i+1);
        }
    }
    
    private void swap(int[] nums, int i, int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

方法二:  上面的方法是 nlogn解法, 如何寻求一个On 的解法。

对于O(n) 显然只能扫描一遍数组,具体算法如下:

1. 在even index 上,比如index = 0, 如果  nums[i] > nums[i+1], 就交换

2.  在odd index 上, 比如index=1, 如果 nums[i] <nums[i+1] 就交换。

如何证明这个算法的正确性,用数学归纳法 Mathematical Induction, 可以证明。

证明如下: 假设已经用上面算法进行了排序,得到了:

a0<=a1>=a2<=a3>=a4<=....ak...

对于n = k+1 的情况,

if n = k+1 is even( 偶数需要在小的位置上), 说明 ak>=a(k+1) ,

如果 a(k+1) > a(k+2), 进行交换, 得到 ak >= a(k+2) <=a(k+1), 可以保持序列形状

如果a(k+a) <a(k+2)   ,不用交换, 仍然可以保持ak<=a(k+1)<=a(k+2) , the order is also correct.

同理, if n =k+1 is odd ,仍然可以用归纳法证明。

class Solution {
    public void wiggleSort(int[] nums) {
        
     for(int i=0; i<nums.length-1; i++){
         if(i%2 ==0 && nums[i] > nums[i+1]  || i%2==1 && nums[i] <nums[i+1])  {   //the condition need to swap
             swap(nums,i,i+1);
         }     
      }
        
    }
    
    private void swap(int[] nums, int i, int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

 

 

对于324 把等于号去掉,保持严格的递增或者递减顺序: 

Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]....

去掉等于号,难度增加了很多,毕竟就算直接排序好了,也难保持严格递增。

nlg(n)的算法:

1. 先排序, 然后还分成左边一半和右边一半, 例如 4 5 5  6 7,  那么left = 4 5 5, right = 6 7 

2. 然后从大到小 每次依次 从左边选一个数 放入,  left =5, right =7  然后 left =5, right =6,  再次 left =4 ,得到  5 7 5 6 4

问题, 什么情况下 无解, 比如有重复数 超过半数数组时, 4 , 5 ,5 5 ,6 则无解, 等于半数仍然有解 例如 4 5 5 6 ,可以变成  5 6 4 5

还有需要注意问题是 左边和右边各方一半的写法。

class Solution {
    public void wiggleSort(int[] nums) {
        int[] sorted = nums.clone();
        Arrays.sort(sorted);
        
        int mid = (sorted.length-1)/2;
        
        int left = mid; // len =5, mid = 2,  if len = 4, mid =1
        int right = sorted.length-1;
        
        for(int i=0; i<sorted.length ; i=i+2){
            nums[i] = sorted[left];
            if(i+1<sorted.length) nums[i+1] = sorted[right];
            left --;
            right --;
        }
        
    }
}

 

posted on 2019-01-15 03:07  KeepAC  阅读(81)  评论(0编辑  收藏  举报