【问题标题】:Java array orderJava 数组顺序
【发布时间】:2020-07-19 23:17:14
【问题描述】:

我有以下数组:

int [] mi_array= {9,4,0,0,4,0,3,0,1,8,0};

我想对左边0以外的数字排序,在右边排序0,但是发现函数踩到了其中一个数字。

输出必须是

{9,4,4,3,1,8,0,0,0,0,0}

public class Array {

    public static void main(String[] args) {
        int [] mi_array= {9,4,4,3,1,8,0,0,0,0,0};
        
        int x=0;
        int y=mi_array.length-1;
        for (int i=0;i<mi_array.length;i++)
            
        
            if(mi_array[i]!=0) {
        
                mi_array[x]=mi_array[i];
                x++;
            }
            else {              
                mi_array[y]=mi_array[i];
                y--;
            }
            
        for (int i=0;i<mi_array.length;i++)
            
            System.out.println(mi_array[i]);
            System.out.println(x);
            
}
    
}

【问题讨论】:

  • 其实非零应该往左边走,我表达错了,顺序无所谓

标签: java arrays foreach


【解决方案1】:

试试这个。

int[] mi_array = {9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0};
for (int i = 0, j = i + 1, s = mi_array.length; j < s;)
    if (mi_array[i] == 0) {
        mi_array[i] = mi_array[j];
        mi_array[j] = 0;
        ++j;
    } else if (++i >= j)
        j = i + 1;
System.out.println(Arrays.toString(mi_array));
// -> [9, 4, 4, 3, 1, 8, 0, 0, 0, 0, 0]

【讨论】:

    【解决方案2】:

    您可以使用filterIntStream.concat将数组中不为0的部分与为0的部分合并。

    final int[] mi_array = { 9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0 };
    final int[] result = IntStream.concat(Arrays.stream(mi_array).filter(i -> i != 0), 
        Arrays.stream(mi_array).filter(i -> i == 0)).toArray();
    System.out.println(Arrays.toString(result));
    

    Demo!

    您也可以这样做:

    final int[] mi_array = { 9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0 };
    final int[] result = new int[mi_array.length];
    final AtomicInteger idx = new AtomicInteger();
    Arrays.stream(mi_array).filter(i -> i != 0).forEach(val -> result[idx.getAndIncrement()] = val);
    System.out.println(Arrays.toString(result));
    

    【讨论】:

      【解决方案3】:

      这里的主要问题是您覆盖了尚未覆盖的数字。

         if (mi_array[i] != 0) {
             mi_array[x] = mi_array[i];
             x++;
         }
      

      x 在这段代码中永远不能超过i;它像 i 一样从 0 开始,并且每个循环最多增加 1(并且 i 每个循环增加 1)。所以,这里没问题;在“最糟糕”的情况下,这是 mi_array[i] = mi_array[i];,它什么都不做。

      然而...

          } else {              
            mi_array[y]=mi_array[i];
            y--;
          }
      

      这更成问题。给定输入 {9,4,0,0,4,0,3,0,1,8,0};,当 i 为 2 时,mi_array[i] 为 0,因此此代码运行。 y 仍然是 10,所以这将最终运行:mi_array[10] = 0;。第二个 0 在 i 为 3 时出现,并最终运行:mi_array[9] = 0;。那时,索引 9 处的8你删除了它。无法恢复。

      解决方案

      愚蠢的解决方案是复制数组;编辑副本,参考原件(您根本不会更改)。您实际上并不需要副本。这段代码将写回每个数字,所以只需创建一个相同大小的新数组并写入。

      稍微优雅一点的解决方案根本不会写 0。相反,它只写入非零(因为该代码不能覆盖任何内容,如前所示),然后在最后用零覆盖其余部分。现在你不需要副本了。

      【讨论】:

        【解决方案4】:

        O(n),两指针方法:

        public static void shiftZeroesRight(int[] array) {    
            int notZeroPos;
            for (int i = 0; i < array.length; i++) {
                if (array[i] != 0)
                    continue;
        
                notZeroPos = i + 1;
                while (notZeroPos < array.length && array[notZeroPos] == 0)
                    ++notZeroPos;
            
                if (notZeroPos >= array.length)
                    break;
            
                array[i] = array[notZeroPos];
                array[notZeroPos] = 0;
            }    
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-01-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-26
          • 1970-01-01
          相关资源
          最近更新 更多