【问题标题】:fix34 codingbat java —why wouldn't this work?fix34 codingbat java — 为什么这不起作用?
【发布时间】:2026-02-23 08:10:01
【问题描述】:

返回一个数组,其中包含与给定数组完全相同的数字,但重新排列,以便每个 3 后面紧跟一个 4。不要移动 3,但每隔一个数字可以移动。该数组包含相同数量的 3 和 4,每个 3 后面都有一个不是 3 的数字,并且 3 出现在数组中的任何 4 之前。这是link .

下面是我的代码。

public int[] fix34(int[] nums) {
  for(int k = 0; k<nums.length; k++)
  {
    if(nums[k] == 3)
    {
      int jay = nums[k+1];
      for(int j = 0; j<nums.length; j++)
      {
        if(nums[j] == 4)
        {
          nums[k+1] = nums[j];
          nums[j] = jay;
        }
      }
    }
  }
  return nums;

我想这样做,如果我们找到数字 3,我们会继续寻找 4(可能在 3 之前或之后),然后将 4 与紧接在 3 后面的数字切换。但是,由于它不适用于所有情况,我猜我的代码并没有完全做到这一点。或者,这是一个逻辑错误吗?任何帮助将不胜感激! (我知道还有其他一些解决方案,但我想了解我的问题到底是什么。)

【问题讨论】:

  • 对于像这样的情况,您无法通过查看代码来找出代码的问题,使用调试器单步执行程序非常有帮助。任何主流 IDE 都支持这一点。调试器允许您在任何给定点停止程序流并检查该范围内所有可见变量的状态。

标签: java arrays for-loop if-statement


【解决方案1】:

我保留你的逻辑并进行一些更改。
在找到 4 并进行交换之后,内部循环需要 break
同样在寻找 4 时,绕过 3 之后的任何 4:

public static int[] fix34(int[] nums) {
    for(int k = 0; k < nums.length; k++) {
        if(nums[k] == 3) {
            int jay = nums[k+1];
            if (jay != 4) {
                for (int j = 1; j < nums.length; j++) {
                    if (nums[j] == 4 && nums[j - 1] != 3) {
                        nums[k + 1] = 4;
                        nums[j] = jay;
                        break;
                    }
                }
            }
        }
    }
    return nums;
}

public static void main(String[] args) {
    int[] array1 = {1, 3, 1, 4};
    int[] array2 = {1, 3, 1, 4, 4, 3, 1};
    int[] array3 = {3, 2, 2, 4};

    System.out.println(Arrays.toString(array1) + "-->" + Arrays.toString(fix34(array1)));
    System.out.println(Arrays.toString(array2) + "-->" + Arrays.toString(fix34(array2)));
    System.out.println(Arrays.toString(array3) + "-->" + Arrays.toString(fix34(array3)));
}

将打印

[1, 3, 1, 4]-->[1, 3, 4, 1]
[1, 3, 1, 4, 4, 3, 1]-->[1, 3, 4, 1, 1, 3, 4]
[3, 2, 2, 4]-->[3, 4, 2, 2]

【讨论】:

    【解决方案2】:

    每次找到3 时,您都会在0 重新启动j。相反,您需要跟踪您处理的最后一个 4 的位置,然后开始寻找下一个:

    public int[] fix34(int[] nums) {
        int last4 = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == 3) {
                while (nums[last4] != 4) {
                    ++last4;
                }
                nums[last4] = nums[i + 1];
                nums[i + 1] = 4;
                ++last4;
            }
        }
        return nums;
    }
    

    【讨论】:

      【解决方案3】:

      您的代码中存在逻辑错误。每次检查 nums[k] == 3 时,都会运行内部循环,它将 3 之后的元素与它在数组中找到的 first 4 交换。如果我说明它(尽管很糟糕):

      如果 nums[k] != 3 我们只是继续循环,因为它什么都不做。

      您的示例数组 = {1,3,2,5,3,4,4}

      当 k == 1 时,nums[k] == 3 为真。

      所以它运行内部循环并且数组变成这样:

      它交换索引 2 处的 2 和索引 5 处的 4,因为第一个元素 4 在索引 5 处找到

      第一次执行内循环后的数组:{1,3,4,5,3,2,4}

      然后它什么都不做,直到它到达 k == 4

      当它达到 k == 4 时,nums[k] == 3 为真

      所以它运行内部循环并且数组变成这样:

      第二次执行内部循环后的结果数组:{1,3,2,5,3,4,4}

      如您所见,它将前 4 个(索引 2 处)与索引 5 处的 2 个交换。但前 4 个已正确放置(通过内部循环的第一次执行)并且不应移动。因此,您需要跟踪正确放置的最后一个元素 4,并将内部循环的开始设置在最后一个元素之后。让我知道这是否有意义。

      就目前而言,您的程序正在执行此操作:找到第一个 4 元素并将其放在最后一个 3 元素之后(并且中间的一些元素被交换)。

      【讨论】:

        【解决方案4】:

        你也可以在一个while循环中完成,干杯!

        public int[] fix34(int[] nums) {
        
          int start = 0;
          int end = nums.length-1;
        
          boolean is3 = false;
          boolean is4 = false;
        
        
          while( start < nums.length-1 ){
        
            if(nums[start] == 3){
              is3 = true;
            }
        
            if(nums[end] == 4){
              is4 = true;
            }
        
        
            if(is3 && is4){
              int temp = nums[start+1];
              nums[start+1] = nums[end];
              nums[end] = temp;
        
              is3 = false;
              is4 = false;
            }
        
        
        
            if(is3){
              end--;
              continue;
            }
        
            start++;
          }
          return nums;
        
        }
        

        【讨论】: