【问题标题】:Reordering numbers in an array [closed]重新排序数组中的数字[关闭]
【发布时间】:2020-10-30 05:35:31
【问题描述】:

我正在尝试解决一个 leetcode 问题:

给定一个数组 nums,编写一个函数将所有 0 移动到它的末尾,同时保持非零元素的相对顺序。 例子: 输入:[0,1,0,3,12] 输出:[1,3,12,0,0]

而且我认为我有正确的解决方案,但我只是不确定为什么我得到它不正确。

class Solution {
    public void moveZeroes(int[] nums) {
        for (int i = 0; i > nums.length;i++) {
            int j= i;
            while ((j<nums.length) && (nums[j]==0)){
                j++;
            }
            if (j<nums.length){
                nums[i]=nums[j];
                nums[j]=0;
            }
        }
        
    }
}

【问题讨论】:

  • i &gt; nums.length 在 for 循环中。这使得永远不会执行 for 循环。应该是i &lt; nums.length
  • 试试0,1,0,0,0,3,12这样的案例
  • 这是一个分区问题,你可以尝试一个通用的分区解决方案,这可能会使代码更简洁,例如:stackoverflow.com/a/46958064/5698534

标签: java arrays sorting indexing


【解决方案1】:

您正在使用i &gt; nums.length,这就是不执行循环的原因

您需要一个非零值的索引。在我的解决方案中,j 用于非零值索引意味着当您找到一个非零值集 j 索引并增加它时。如果j 小于i 或等于,则意味着将找到零,然后设置它。

  public void moveZeroes(int[] nums) {
    int j = 0;
    for (int i = 0; i < nums.length; i++) {
      if (nums[i] != 0) {
        nums[j] = nums[i];
        j++;
      }
      if (j <= i) {
        nums[i] = 0;
      }
    }
  }

【讨论】:

    【解决方案2】:

    for 循环不正确(必须是i &lt; nums.length),另外,如果无事可做,您的解决方案也不起作用:

        final int[] expectedArray = {1,2,0,0};
        final String expectedString = Arrays.toString(expectedArray);
        
        int[] nothingToDo = {1,2,0,0};
        moveZeroes(nothingToDo);
        assertEquals(expectedString, Arrays.toString(nothingToDo));
    

    产量:

    org.junit.ComparisonFailure: expected:<[[1, 2], 0, 0]> but was:<[[0, 0], 0, 0]>
    

    自己写一些测试用例,看看有什么问题。

    在你的情况下:

        if (j<nums.length){
                nums[i]=nums[j];
                nums[j]=0;
            }
    

    是错误的,因为您将ij 交换,即使i == jnums[i] != 0 也是如此。

    由于我认为您不是在寻求可行的解决方案,因此我不会提供。但这是我的测试用例:

    @Test
    public void testEmptyArray() {
        int[] array = new int[0];
        moveZeroes(array);
        assertEquals(0,array.length);
    }
    
    @Test
    public void testZeroOnlyArrays() {
        int[] array = {0,0,0,0};
        final String arrayString = Arrays.toString(array);
        moveZeroes(array);
        assertEquals(arrayString, Arrays.toString(array));;
    }
    
    @Test
    public void mixedTest() {
        
        int[] array = {0,1,0,2};
        final int[] expectedArray = {1,2,0,0};
        final String expectedString = Arrays.toString(expectedArray);
        moveZeroes(array);
        assertEquals(expectedString, Arrays.toString(array));;
        
        int[] nothingToDo = {1,2,0,0};
        moveZeroes(nothingToDo);
        assertEquals(expectedString, Arrays.toString(nothingToDo));
    }
    

    【讨论】:

      【解决方案3】:

      你可以用一个指针解决这个问题 O(N)。这会通过:

      public class Solution {
          public static void moveZeroes(int[] nums) {
              if (nums == null || nums.length == 0)
                  return;
      
              int pos = 0;
              for (int num : nums)
                  if (num != 0)
                      nums[pos++] = num;
              while (pos < nums.length)
                  nums[pos++] = 0; 
          }
      }
      

      参考

      • 有关其他详细信息,您可以查看Discussion Board。有很多公认的解决方案,有各种languages 和解释、高效的算法,以及渐近的time/space 复杂性分析1, 2

      【讨论】:

      • 结果是一样的,但你并没有像任务所暗示的那样移动零。您只是将非零复制到前面,然后在末尾插入 0。
      【解决方案4】:

      “for”循环应该是:for (int i = 0; i &lt; nums.length;i++) 然后,您的循环将从 0 开始在数组索引上运行,直到达到数组的长度。

      当前代码甚至不会像您定义的那样进入循环 i=0 并且循环条件仅在它大于数组大小时才运行循环: (i > nums.length) 这当然不是真的

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-22
        • 1970-01-01
        • 2021-09-27
        • 2014-08-09
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        相关资源
        最近更新 更多