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

posted on 2014-12-20 17:00  Yu's Garden  阅读(3527)  评论(0编辑  收藏  举报

导航