【问题标题】:Rearrange int array so that all the negative numbers come before the positivite numbers重新排列 int 数组,使所有负数都在正数之前
【发布时间】:2017-02-19 16:57:25
【问题描述】:

我正在尝试编写一个方法,该方法采用 ints 数组,然后重新排列数组中的数字,使负数排在第一位。数组不需要以任何方式排序。唯一的要求是解必须是线性的,并且不使用额外的数组。

输入:

{1, -5, 6, -4, 8, 9, 4, -2}

输出:

{-5, -2, -4, 8, 9, 1, 4, 6}

现在,作为 Java 和一般编程的菜鸟,我不能 100% 确定什么是线性解决方案,但我的猜测是它必须是一个不在循环中使用循环的解决方案。

我目前有一个糟糕的解决方案,我知道它不起作用(我也明白为什么),但我似乎想不出任何其他解决方案。如果允许我在循环或附加数组中使用循环,但我不被允许,这项任务会很容易。

我的代码:

public static void separateArray(int[] numbers) {
    int i = 0;
    int j = numbers.length-1;
    while(i<j){

        if(numbers[i] > 0){
            int temp;
            temp = numbers[j];
            numbers[j] = numbers[i];
            numbers[i] = temp;
            System.out.println(Arrays.toString(numbers));
        }

        i++;
        j--;
    }
}

【问题讨论】:

  • 如果你要自己解决这个问题,不写程序,你会怎么做?您能否采用该解决方案并将其分解为可以构成您的程序基础的一系列步骤?
  • 您实际上已经很接近了。您的代码结构是正确的,但您的比较并不完全正确,您的循环边界有错误,并且您的输出语句位于错误的位置。
  • @scottb 我已经这样做了好几次,但我总是意识到我刚刚提出的解决方案是非线性的。我总是不止一次循环播放它,这让我发疯!
  • 当你不知道你刚刚输入i的数字是正数还是负数时,你怎么能执行i++
  • @Schytheron 使用递归怎么样?

标签: java arrays sorting int


【解决方案1】:

您只需更改一行即可(大部分)使其正常工作。但是您需要更改两行以正确处理输入中的零。我已经用下面的“FIXME”cmets 强调了这两个最低限度的必要更改:

public static void separateArray(int[] numbers) {
    int i = 0;
    int j = numbers.length-1;
    while(i<j){
        if(numbers[i] > 0){ // FIXME: zero is not a "negative number"
            int temp;
            temp = numbers[j];
            numbers[j] = numbers[i];
            numbers[i] = temp;
        }
        i++; // FIXME: only advance left side if (numbers[i] < 0)
        j--; // FIXME: only decrease right side if (numbers[j] >= 0)
    }
}

【讨论】:

  • 谢谢你!我确实注意到您的代码进行了不必要的交换,因此我对其进行了一些改进。检查我的帖子编辑!
  • 当输入 start 和 end 有类似 (10,-2​​0,40) 的符号时,此程序将失败
  • @muzamil 我没有提供解决方案的代码。我只用 cmets 标记了原始代码,显示了需要修复的地方。所以你自己必须实现标记为“FIXME”的行。我把它留给学生做练习。这显然是学生的问题。
  • @muzamilsiddiq 我从问题中复制了非工作代码,然后添加了两个修复程序以回答问题
  • 缺少修复:仅当 numbers[j] &gt; 0if (numbers[j] &gt; 0) j-- 时,将 j 减少 1。 @Schytheron 示例输入:[1, -2, -3, -4, 5, -6, 7, -8, 9, -10, -11, -12, 20]
【解决方案2】:

您使用两个指针ij 的方法是一个好的开始。

考虑一下您立即(空洞地)设置的循环不变量:

  • 0(含)到i(不含)范围内的元素为负数;
  • j(不包括)到 numbers.length(不包括)范围内的元素是非负的。

现在,您希望能够将ij 一起移动,直到它们相互通过,同时保持循环不变:

  • 如果i &lt; numbers.lengthnumbers[i] &lt; 0,可以将i加1;
  • 如果j &gt;= 0numbers[j] &gt;= 0,可以将j减1;
  • 如果i &lt; numbers.lengthj &gt;= 0,那么numbers[i] &gt;= 0numbers[j] &lt; 0。交换它们。

如果你一直应用这个策略直到i == j + 1,那么你最终会得到想要的情况,那就是:

  • numbers[a] &lt; 0 for a in [0..i)
  • numbers[a] &gt;= 0 for a in (j..numbers.length),也写成numbers[a] &gt;= 0 for a in (i-1..numbers.length),也写成numbers[a] &gt;= 0 for a in [i..numbers.length)

因此,您已经对数组进行了分区,以便所有负数都位于i-th 元素的左侧,所有非负数都位于i-th 元素的右侧或右侧。

希望这个算法应该易于理解,从而易于实现。

【讨论】:

  • 谢谢!您的解决方案有效,但我选择帕特里克帕克的解决方案只是因为它更容易解决......对不起;(
  • 没问题。我不想给你代码,因为我认为最好展示如何推理它。
【解决方案3】:

线性解决方案是具有run-time complexity Big-Oh(n) 的解决方案,也称为 O(n),换句话说,您只需循环整个数组一次。要按线性时间排序,您可以尝试以下排序算法之一:

【讨论】:

  • 所有这些排序算法似乎都需要一个额外的数组(我不允许这样做)。我知道循环内的循环不被认为是线性的,但是如果一个解决方案包含多个循环,它是否被认为是线性的?例如,我在第一个循环完成后执行第二个 for 循环。在我看来,它似乎是线性的,因为复杂度仅为 2*n(如果 n 是数组中元素的数量)。
  • 是的,只要它们不是嵌套循环,您就可以这样做。复杂度将是 n+n+n+..+n 等等。
【解决方案4】:

只有当所有负数都位于右半边且正数位于左半边时,您的代码才有效。例如,您的代码将 6 与 9 交换,两者都是正数。所以,这取决于你的数组元素的顺序。正如 scottb 所说,先试着用手做,然后你会发现哪里做错了。此外,在while中打印你的数组

【讨论】:

    【解决方案5】:
    //Move positive number left and negative number right side
    
    public class ArrangeArray {
        public static void main(String[] args) {
            int[] arr = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
            for (int i = 0; i < arr.length; i++) {
                System.out.print(" " + arr[i]);
            }
            int temp = 0;
            for (int i = 0; i < arr.length; i++) {
                // even
                if (arr[i] < 0) {
                    for (int j = i + 1; j < arr.length; j++) {
                        if (arr[j] > 0) {
                            arr[j] = arr[i] + arr[j];
                            arr[i] = arr[j] - arr[i];
                            arr[j] = arr[j] - arr[i];
                            break;
                        }
                    }
                }
            }
            System.out.println("");
            for (int i = 0; i < arr.length; i++) {
                System.out.print(" " + arr[i]);
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      有一个简单的程序可以帮助你。在这个程序中,我采用临时数组并执行项目迭代次数。在那里我开始从右边填充正值,从左边开始填充负值。

       public static void rearrangePositiveAndNegativeValues() {
              int[] a = {10,-2,-5,5,-8};
              int[] b = new int[a.length];
              int i = 0, j = a.length -1;
      
              for (int k = 0; k < a.length ; k++) {
                  if (a[k] > 0) {
                      b[j--] = a[k];
                  } else {
                      b[i++] = a[k];
                  }
              }
      
              System.out.println("Rearranged Values : ");
              printArray(b);
          }
      

      【讨论】:

        【解决方案7】:
        package ArrayProgramming;
        
        import java.util.ArrayList;
        import java.util.Arrays;
        
        public class RearrangingpossitiveNegative {
        
        
            public static void main(String[] args) {
                int[] arr= {-1,3,4,5,-6,6,8,9,-4};
                ArrayList<Integer> al = new ArrayList<Integer>();
                for (int i=0;i<arr.length;i++) {
                    if(arr[i]>0) {
                        al.add(arr[i]);
                    }
                }
                for (int i=arr.length-1;i>=0;i--) {
                    if(arr[i]<0) {
                        al.add(arr[i]);
                    }
                }
                System.out.println(al);
            }
        }
        

        【讨论】:

          【解决方案8】:
          from array import *
          size = int(input())
          arr = (array('i' , list(map(int, input().split()))))
          negarr = array('i')
          posarr = array('i')
          for i in arr:
              if i>=0:
                  posarr.append(i)
              else:
                  negarr.append(i)
          
          print(*(negarr+posarr))
          

          我们也可以通过创建两个新数组并根据给定条件向其中添加元素来做到这一点。稍后将它们都加入以产生最终结果。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-05-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-30
            • 1970-01-01
            相关资源
            最近更新 更多