我的荷兰国旗算法出了什么问题?

时间:2009-11-18 21:22:15

标签: java sorting

我正试图像这样打开一个数组:

0, 1, 2, 2, 1, 0, 1, 0, 0, 1, 2

进入这个:

0 0 0 0 1 1 1 1 2 2 2

这是我的代码:

public static int[] sortDNF(int[] tape) {
    int smaller = 0; // everything with index < smaller is 0
    int bigger = tape.length - 1; // everything with index > bigger is 2
    int current = 0; // where we are looking now
    int tmp;

    while (current <= bigger) {
        if (tape[current] == 0) {
            tmp = tape[smaller];
            tape[smaller] = tape[current];
            tape[current] = tmp;
            smaller++;
        }
        if (tape[current] == 2) {
            tmp = tape[bigger];
            tape[bigger] = tape[current];
            tape[current] = tmp;
            bigger--;
        }
        current++;
    }

    return tape;
}

这就是它产生的:

 0  0  0  1  1  1  1  0  2  2  2 

我的问题是什么?

8 个答案:

答案 0 :(得分:4)

猜测:

每次循环都不应该增加电流,因为它应该代表1和未知数之间的分区。例如,当您点击前2时,您最终将其与另外2个交换,然后继续前进。事实上,2后来换成0是偶然的。较小和当前之间的元素应始终为1,并且会被打破。

current ++只能在磁带[current]中完成!= 2个案例。当磁带[current] = 0时可以这样做,因为你没有改变[较小 - &gt; current] = 1-only条件。当磁带[current] = 1时移动它是可以的,因为它满足了1-only条件。

......但我还没试过。

答案 1 :(得分:2)

对于那些没有研究过这个问题的人来说,排序就足以提供一个解决方案,但它已经(或可能)不必要了。解决DNF问题只需要将所有类似项目一起移动,但您不必按任何特定顺序放置不相等的项目。

使用预期的O(N)复杂度来解决DNF非常容易,其中(大多数正常形式的)排序具有O(N lg N)复杂度。不是重新排列输入元素,而是简单地计算具有任何给定值的元素,然后打印出正确数量的元素,这样更容易。由于不相等元素的顺序无关紧要,因此通常将计数存储在哈希表中。

答案 2 :(得分:1)

问题是您在链中稍后回复(可能不存在)值以交换错误跳过的1个值,尝试您的算法:

1 2 0

2在正确的位置交换,但当前指数已经超过指数0的最终结果,导致:

1 0 2

因此,在检查该索引处的新值之前,请不要增加当前值。

答案 3 :(得分:1)

public static int[] sortDNF(int[] tape) {
    int smaller = 0; // everything with index < smaller is 0
    int bigger = tape.length - 1; // everything with index > bigger is 2
    int current = 0; // where we are looking now
    int tmp;

    while (current <= bigger) {
            if (tape[current] == 0) {
                    tmp = tape[smaller];
                    tape[smaller] = tape[current];
                    tape[current] = tmp;
                    smaller++;
            }
            else if (tape[current] == 2) {
                    tmp = tape[bigger];
                    tape[bigger] = tape[current];
                    tape[current] = tmp;
                    bigger--;
            }
            current++;
    }

    return tape;
}

答案 4 :(得分:1)

您需要在检查1期间增加电流并检查2.当您检查3时,您只需要递减更大。这是工作解决方案。 BTW这适用于1-3之间的值数组。如果您愿意,可以将其更改为0-2。

程序产生以下输出,给定一个随机数组,如下所示:

原始数组:[1,3,3,3,2,2,2,1,2,2,1,3,3,2,1,1,3]

排序数组:[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,3]

private static int[] sortUsingDutchNationalFlagProblem(int[] array) 
{
    System.out.println("Original Array : " + Arrays.toString(array));
    int smaller = 0;    // everything with index < smaller is 1
    int bigger  = array.length - 1; // everything with index > bigger is 3
    int current = 0;        // where we are looking now
    int tmp;
    while (current <= bigger) {
            if (array[current] == 1) {
                    tmp            = array[smaller];
                    array[smaller] = array[current];
                    array[current] = tmp;
                    smaller++;current++;
            }
            if(array[current] == 2)
                current++;
            if (array[current] == 3) {
                    tmp            = array[bigger];
                    array[bigger]  = array[current];
                    array[current] = tmp;
                    bigger--;
            }
    }
    System.out.println("Sorted Array   : " + Arrays.toString(array));
    return array;
}

答案 5 :(得分:0)

这是我使用Java的方法

public static void dutchNationalFlagProblem(int[] input) {
    int low=0, mid=0, high = input.length -1;
    while(mid <=high) {
        switch (input[mid]) {
            case 0:
                swap(input, low++, mid++);  
                break;
            case 1:
                mid++;  
                break;
            default :
                swap(input, mid, high--);
                break;
        }
    }       
}

private static void swap(int[] input, int firstIndex, int secondIndex) {
    int temp = input[firstIndex];
    input[firstIndex] = input[secondIndex];
    input[secondIndex] = temp;

}

以下是相应的测试用例

@Test
public void dutchNationalFlagProblemTest() {
    int[] input = new int[]{0,1,0,2,2,1};
    ArrayUtils.dutchNationalFlagProblem(input);
    assertThat(input, equalTo(new int[]{0,0,1,1,2,2}));
}

答案 6 :(得分:0)

下面的程序给出了正确的结果,你们看到这种简单的无害编程方法中的任何问题吗?


public class Test {
    public static void main(String[] args) {
        int arr[] = {1, 2, 0, 2, 1, 1, 1, 0, 0, 2, 2, 1, 0, 1, 2, 0, 2};
        int x0 = 0, x1 = 0, x2 = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == 0)
                x0++;
            if (arr[i] == 1)
                x1++;
            if (arr[i] == 2)
                x2++;
        }
        int i = 0;
        for (int j = i; j < x0; j++)
            arr[i++] = 0;
        for (int j = i; j < x0+x1; j++)
            arr[i++] = 1;
        for (int j = i; j < x0+x1+x2; j++)
            arr[i++] = 2;

        printArray(arr);

    }

    private static void printArray(int[] arr) {
        for (int a : arr) {
            System.out.print(a + " ");
        }
    }
}

答案 7 :(得分:-1)

我打算提出一个更简单的解决方案: - )

public static int[] sortDNF(int[] tape) {
  Arrays.sort(tape);
  return tape;
}

对于您的解决方案有什么问题,当前元素为2并且它与列表末尾附近的元素交换时,与其交换的元素可能 2,但你正在增加电流而不是再次看这个位置。