不应该在下面代码的内循环中使用break更有意义吗?

时间:2016-10-15 20:38:10

标签: java algorithm

我正在尝试解决名为 fix34 的问题。它期望返回一个包含与给定数组完全相同的数字的数组,但重新排列,以便每3个后面紧跟一个4.不要移动3,但每个其他数字可能会移动。该数组包含相同数量的3和4,每3个后面有一个不是3的数字,并且在任何4之前数组中出现3。

我想出了以下代码:

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

现在,问题是如果我不在内循环中使用 break ,它会通过所有测试,否则不会!对我来说,使用它更有意义,因为内部循环可能最终用 temp 替换所有4个。

请澄清我为什么错?感谢。

2 个答案:

答案 0 :(得分:2)

原因是您的break当前在第二个for循环的第一次迭代中执行。如果在if(condition)语句后没有添加大括号,则只有在条件为真后才执行第一行:

if (nums[j] == 4) nums[j] = temp; // Only this gets executed if the condition is true
break; // the condition has no effect on this statement

由于你只想满足条件break,你应该这样做:

if (nums[j] == 4) {
    nums[j] = temp;
    break;
}

作为旁注,您只需一次迭代即可更有效地解决此问题。请参阅@ dasblinkenlight的答案。

修改: 好的,我已经仔细研究了这个问题并意识到问题是当你省略break时你的版本甚至没有真正起作用。它通过codingBat上的所有测试这一事实纯属巧合。

正如你已经说明的那样,没有break可能会导致循环用temp变量覆盖太多的数组条目,这正是这种情况下发生的情况。它恰好是给定测试用例的正确值,这使得它看起来像代码是正确的。

如果您只是添加一个break,即使它应该在第一眼看到,代码不起作用的原因是:问题只表明在第一个4之前没有3 1}}。它并没有说两个4之间只有一个3。这意味着您不能从j = i + 2开始搜索要替换的4,因为它实际上可能在i之前。

我用不同于@dasblinkenlight提出的方法编写了一个解决方案(因为我不只是想复制他的算法)。我的版本在数组上循环两次,这仍然意味着它是O(n):

public int[] fix34(int[] nums) {
    int[] result = new int[nums.length];
    ArrayList otherNumbers = new ArrayList();
    for(int i = 0; i < nums.length; i++){
        if(nums[i] == 3) {
            result[i] = 3;
            result[i+1] = 4;
        } else if(nums[i] != 4) {
            otherNumbers.add(nums[i]);
        }
    }
    for(int i = 0; i < nums.length; i++) {
        if(result[i] != 3 && result[i] != 4)
            result[i] = (Integer)otherNumbers.remove(0);
    }
    return result;
}

答案 1 :(得分:2)

这可以通过一个循环来解决:

  • 从右到左遍历阵列。由于你要退步,你会在每三个人之前看到足够的四肢。
  • 保持阅读指数和写作指数。
  • 每当您在阅读索引处看到四个时,请跳至较早的索引
  • 每当你看到一个三,写一个四,提前写入索引,然后写一个三
  • 按原样复制任何其他号码

在循环结束时,将根据需要重新排列数组。

int[] data = new int[] {1, 2, 3, 5, 5, 4, 3, 7, 3, 4, 2, 3, 2, 3, 4, 4, 4};
// Expected:            1, 2, 3, 4, 5, 5, 3, 4, 7, 3, 4, 2, 3, 4, 2, 3, 4
int r = data.length-1;
int w = data.length-1;
while (r >= 0) {
    switch(data[r]) {
        case 3:
            data[w--] = 4;
            data[w--] = 3;
        case 4:
            break;
        default:
            data[w--] = data[r];
            break;
    }
    r--;
}
for (int i = 0 ; i != data.length ; i++) {
    System.out.print(data[i]+" ");
}
System.out.println();

Demo.