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.

Lintcode: Interleaving Positive and Negative Numbers 解题报告

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

你可能感兴趣的:(number)