• Lintcode: Interleaving Positive and Negative Numbers 解题报告


    Interleaving Positive and Negative Numbers

    原题链接 : http://lintcode.com/zh-cn/problem/interleaving-positive-and-negative-numbers/

    Given an array with positive and negative integers. Re-range it to interleaving with positive and negative integers.

    注意

    You are not necessary to keep the original order or positive integers or negative integers.

    样例

    Given [-1, -2, -3, 4, 5, 6], after re-range, it will be [-1, 5, -2, 4, -3, 6] or any other legal answer.

    挑战

    Do it in-place and without extra memory.

    SOLUTION 1:

    1. 先用parition把数组分为左边为负数,右边为正数。

    2. 如果负数比较多,把多余的负数与尾部的值交换。(这样多余的数会放在数组的末尾)

    3. left 指向数组的左边,right指向数组的右边减掉多余的数。

    4. 第3步中,根据是正数多,还是负数多,起始位置要变一下。正数多,我们希望开始的是正数:

    例如 3 -1 2

    负数多,我们希望开始的是负数,如 -1 3 -2

    5. 不断交换left, right指针,并一次前进步长2. 直到left, right 相遇。

     1 class Solution {
     2    /**
     3      * @param A: An integer array.
     4      * @return an integer array
     5      */
     6     // SOLUTION 2: 判断正数多还是负数多。 
     7     public static int[] rerange(int[] A) {
     8         // write your code here
     9         
    10         // Check the input parameter.
    11         if (A == null || A.length == 0) {
    12             return A;
    13         }
    14         
    15         int len = A.length;
    16         
    17         int left = -1;
    18         int right = A.length;
    19         
    20         // divide the negative and positive integers.
    21         while (true) {
    22             while (left < A.length - 1 && A[++left] < 0);
    23             
    24             while (left < right && A[--right] > 0);
    25             
    26             if (left >= right) {
    27                 break;
    28             }
    29             
    30             swap(A, left, right);
    31         }
    32         
    33         // LEFT: point to the first positive number.
    34         int negNum = left;
    35         int posNum = len - left;
    36         
    37         int les = Math.min(negNum, posNum);
    38         int dif = Math.abs(negNum - posNum);
    39         
    40         // 如果负数比较多,把多的负数扔到后面去
    41         if (negNum > posNum) {
    42             int cnt = dif;
    43             int l = les;
    44             int r = len - 1;
    45             while (cnt > 0) {
    46                 swap(A, l, r);
    47                 l++;
    48                 r--;
    49                 cnt--;
    50             }
    51             
    52             // 负数多的时候,负数在前,反之,正数在前
    53             left = -1;
    54             // 跳过右边不需要交换的值
    55             right = A.length - dif;
    56         } else {
    57             // 正数在前
    58             left = -2;
    59             // 跳过右边不需要交换的值
    60             right = A.length - dif + 1;
    61         }
    62         
    63         /*
    64           -1 -2 -5 -6  3  4  les = 2;
    65           4  -2 -5 -6  3 -1
    66         */
    67         // swap the negative and the positive
    68         while (true) {
    69             left += 2;
    70             right -= 2;
    71             
    72             if (left >= les) {
    73                 break;
    74             }
    75             swap(A, left, right);
    76         }
    77 
    78         return A;
    79    }
    80    
    81    public static void swap(int[] A, int n1, int n2) {
    82        int tmp = A[n1];
    83        A[n1] = A[n2];
    84        A[n2] = tmp;
    85    }
    86 }
    View Code

    SOLUTION 2(December 23th Refresh)

    1. 扫一次确定是正数多还是负数多

    2. 把奇数索引的所有的数字进行partition,如果是正数多,把正数放在后面,否则负数放在后面。

    3. 令Index 1 = 奇数列,index 2 = 偶数列,扫描一次,遇到不符合正负条件的数字进行交换即可

      1 public static void swap(int[] A, int n1, int n2) {
      2        int tmp = A[n1];
      3        A[n1] = A[n2];
      4        A[n2] = tmp;
      5    }
      6    
      7    /*
      8    Solution 2:
      9    */
     10    public static int[] rerange(int[] A) {
     11         // write your code here
     12         
     13         // Check the input parameter.
     14         if (A == null || A.length <= 2) {
     15             return A;
     16         }
     17         
     18         int len = A.length;
     19         
     20         int cntPositive = 0;
     21         
     22         for (int num: A) {
     23             if (num > 0) {
     24                 cntPositive++;    
     25             }
     26         }
     27         
     28         // If positive numbers are more than negative numbers,
     29         // Put the positive numbers at first.
     30         int posPointer = 1;
     31         int negPointer = 0;
     32         
     33         // means 
     34         boolean pos = false;
     35         
     36         if (cntPositive > A.length / 2) {
     37             // Have more Positive numbers;
     38             posPointer = 0;
     39             negPointer = 1;
     40             
     41             pos = true;
     42         }
     43         
     44         int i = 1;
     45         int j = len - 2;
     46         
     47         if (pos) {
     48             while (true) {
     49                 // Put the positive numbers at the end.
     50                 if (i < len && A[i] < 0) {
     51                     i += 2;
     52                 }
     53                 
     54                 if (j > i && A[j] > 0) {
     55                     j -= 2;
     56                 }
     57                 
     58                 if (i >= j) {
     59                     break;
     60                 }
     61                 
     62                 swap(A, i, j);
     63             }
     64         } else {
     65             while (true) {
     66                 // Put the negative numbers at the end.
     67                 if (i < len && A[i] > 0) {
     68                     i += 2;
     69                 }
     70                 
     71                 if (j > i && A[j] < 0) {
     72                     j -= 2;
     73                 }
     74                 
     75                 if (i >= j) {
     76                     break;
     77                 }
     78                 
     79                 swap(A, i, j);
     80             }
     81         }
     82         
     83         // Reorder the negative and the positive numbers.
     84         while (true) {
     85             // Should move if it is in the range.
     86             while (posPointer < len && A[posPointer] > 0) {
     87                 posPointer += 2;
     88             }
     89             
     90             // Should move if it is in the range.
     91             while (negPointer < len && A[negPointer] < 0) {
     92                 negPointer += 2;
     93             }
     94             
     95             if (posPointer >= len || negPointer >= len) {
     96                 break;
     97             }
     98             
     99             swap(A, posPointer, negPointer);
    100         }
    101         
    102         return A;
    103    }
    View Code

    SOLUTION 3(December 23th Refresh):

    在SOL2的基础上改进:

    1. 在统计正负数个数时,把负数放在最后。

    2. 如果发现正数比较多,把数列翻转。

    3. 令Index 1 = 奇数列,index 2 = 偶数列,扫描一次,遇到不符合正负条件的数字进行交换即可

     1 /*
     2    Solution 3:
     3    */
     4    public static int[] rerange(int[] A) {
     5         // write your code here
     6         
     7         // Check the input parameter.
     8         if (A == null || A.length <= 2) {
     9             return A;
    10         }
    11         
    12         int len = A.length;
    13         
    14         int cntPositive = 0;
    15         
    16         // store the positive numbers index.
    17         int i1 = 0;
    18         
    19         for (int i2 = 0; i2 < len; i2++) {
    20             if (A[i2] > 0) {
    21                 cntPositive++;
    22                 
    23                 // Put all the positive numbers at in the left part.
    24                 swap(A, i1++, i2);
    25             }
    26         }
    27         
    28         // If positive numbers are more than negative numbers,
    29         // Put the positive numbers at first.
    30         int posPointer = 1;
    31         int negPointer = 0;
    32         
    33         if (cntPositive > A.length / 2) {
    34             // Have more Positive numbers;
    35             posPointer = 0;
    36             negPointer = 1;
    37             
    38             // Reverse the array.
    39             int left = 0;
    40             int right = len -1;
    41             while (left < right) {
    42                 int tmp = A[left];
    43                 A[left] = A[right];
    44                 A[right] = tmp;
    45                 left++;
    46                 right--;
    47             }
    48         }
    49         
    50         // Reorder the negative and the positive numbers.
    51         while (true) {
    52             // Should move if it is in the range.
    53             while (posPointer < len && A[posPointer] > 0) {
    54                 posPointer += 2;
    55             }
    56             
    57             // Should move if it is in the range.
    58             while (negPointer < len && A[negPointer] < 0) {
    59                 negPointer += 2;
    60             }
    61             
    62             if (posPointer >= len || negPointer >= len) {
    63                 break;
    64             }
    65             
    66             swap(A, posPointer, negPointer);
    67         }
    68         
    69         return A;
    70    }
    View Code

    SOLUTION 4(December 23th Refresh):

    在SOL3的基础上改进:

    翻转数列的一步修改为:把右边的负数移动到左边即可。可以优化复杂度。其它与SOL3一致。

    感谢Lansheep大神提供思路!

     1 /*
     2    Solution 4:
     3    把reverse的步骤简化了一下
     4    */
     5    public static int[] rerange(int[] A) {
     6         // write your code here
     7         
     8         // Check the input parameter.
     9         if (A == null || A.length <= 2) {
    10             return A;
    11         }
    12         
    13         int len = A.length;
    14         
    15         int cntPositive = 0;
    16         
    17         // store the positive numbers index.
    18         int i1 = 0;
    19         
    20         for (int i2 = 0; i2 < len; i2++) {
    21             if (A[i2] > 0) {
    22                 cntPositive++;
    23                 
    24                 // Put all the positive numbers at in the left part.
    25                 swap(A, i1++, i2);
    26             }
    27         }
    28         
    29         // If positive numbers are more than negative numbers,
    30         // Put the positive numbers at first.
    31         int posPointer = 1;
    32         int negPointer = 0;
    33         
    34         if (cntPositive > A.length / 2) {
    35             // Have more Positive numbers;
    36             posPointer = 0;
    37             negPointer = 1;
    38             
    39             // Reverse the array.
    40             int left = 0;
    41             int right = len -1;
    42             while (right >= cntPositive) {
    43                 swap(A, left, right);
    44                 left++;
    45                 right--;
    46             }
    47         }
    48         
    49         // Reorder the negative and the positive numbers.
    50         while (true) {
    51             // Should move if it is in the range.
    52             while (posPointer < len && A[posPointer] > 0) {
    53                 posPointer += 2;
    54             }
    55             
    56             // Should move if it is in the range.
    57             while (negPointer < len && A[negPointer] < 0) {
    58                 negPointer += 2;
    59             }
    60             
    61             if (posPointer >= len || negPointer >= len) {
    62                 break;
    63             }
    64             
    65             swap(A, posPointer, negPointer);
    66         }
    67         
    68         return A;
    69    }
    View Code

    GITHUB:

    https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/lintcode/array/Rerange.java

  • 相关阅读:
    001 云开发基础
    HttpClient 调用外部接口(简单实用)
    MD5加密(简单实现_可自行扩展)
    SAA C02考点梳理
    支配树
    CF1320E 题解
    dp套dp
    20210705模拟赛总结
    20210703模拟赛
    20210629模拟赛总结
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4175620.html
Copyright © 2020-2023  润新知