Java 在O(N)时间内对数组排序

Java 在O(N)时间内对数组排序,java,arrays,algorithm,sorting,Java,Arrays,Algorithm,Sorting,给定整数1,2,3,…,N和字符“(空格)的数组A 我们希望将其排序为[1,2,3,…,N,“],其中我们只能将整数与“”交换,但不能相互交换,因此允许交换(3,”,而不允许交换(1,2) 我的尝试是将空间表示为“-1”,并在O(N)时间内搜索它,然后再次从i=1到N+1,如果我看到例如A[2]=7,我将A[7]与“交换,然后我将A[2]与交换同时跟踪“的位置,因为这是交换的唯一方式,因此7将以A[7]结束(索引移动除外) 我编写的代码如下: public static int[] arrayS

给定整数
1,2,3,…,N
和字符
(空格)的数组
A
我们希望将其排序为
[1,2,3,…,N,“]
,其中我们只能将整数与“”交换,但不能相互交换,因此允许
交换(3,”
,而不允许
交换(1,2)

我的尝试是将空间表示为
“-1”
,并在O(N)时间内搜索它,然后再次从
i=1
N+1
,如果我看到例如
A[2]=7
,我将
A[7]
交换,然后我将
A[2]
交换
同时跟踪
的位置,因为这是交换的唯一方式,因此
7
将以
A[7]
结束(索引移动除外) 我编写的代码如下:

public static int[] arraySort(int[] array){

    int space = 0;

    for(int i = 0; i<array.length; i++ ){
        if(array[i] == -1){
            space = i;
        }
    }

    for(int i = 0; i<array.length; i++){
        if(array[i] != i+1 && array[i] !=-1){
            swap(array, array[i]-1 , space);
            space = array[i]-1;
            swap(array, i, space);
            space = i;
        }
    }
    return array;
}

public static void swap(int[] arr, int ind1, int ind2){

    int temp = arr[ind2];
    arr[ind2] = arr[ind1];
    arr[ind1] = temp;
}
公共静态int[]数组排序(int[]数组){
int空间=0;

对于(int i=0;i使用计数排序技术。始终将空格放在数组的末尾。您有一个大小为N+1的数组。现在,尝试从第一位读取数组。例如,它是3。您应该将3放在数组的第三位。为此,请将数组的当前第三位值与空格交换,然后交换t的第一位他用第三个数组交换第一个数组,然后用数组的最后一个项目交换第一个数组。后一个步骤将用于保持数组末尾的空间

public static int[] arraySort(int[] array){
    int N = array.length - 1;
    for(int i = 0; i < N; i++){
        int currentNum = array[i]-1;
        swap(array, currentNum, N); // swap currentNum-th item with space as the last memebr of the array
        swap(array, i, currentNum); // swap the current item with its place
        swap(array, i, N); // swap the space with the last item.
    }

    return array;
}

public static void swap(int[] arr, int ind1, int ind2){
    int temp = arr[ind2];
    arr[ind2] = arr[ind1];
    arr[ind1] = temp;
}
公共静态int[]数组排序(int[]数组){
int N=array.length-1;
对于(int i=0;i
在上面的代码中,我们假设起始数组中的空格位置在最后一个。如果不是,您可以在
O(N)
中找到它,并将其与数组的最后一个位置交换。

步骤1创建一个查找数组
public static int[] arraySort(int[] array){
    int N = array.length - 1;
    for(int i = 0; i < N; i++){
        int currentNum = array[i]-1;
        swap(array, currentNum, N); // swap currentNum-th item with space as the last memebr of the array
        swap(array, i, currentNum); // swap the current item with its place
        swap(array, i, N); // swap the space with the last item.
    }

    return array;
}

public static void swap(int[] arr, int ind1, int ind2){
    int temp = arr[ind2];
    arr[ind2] = arr[ind1];
    arr[ind1] = temp;
}
将数组设为N+1长,其中查找数组中的每个值都表示它在要排序的数组中的位置。可以将查找[0]设为空间所在的位置。创建这样的数组需要O(N)个时间。 在[7,3,5,4,6,1,2,-1]的情况下,你做一个数组[7,5,6,1,3,2,4,0]

步骤2:将空间移动到阵列的起始位置 您可以通过查找[0]找到空间的当前索引,如果它已经位于索引0,则转到下一步,否则使用索引0进行交换。然后您应该更新循环数组以反映更改。即查找[0处的值]=[空间开始的位置]

步骤3:将空间与数组中的下一个元素交换 现在用
1
交换空间。你可以用查找数组找到它

第4步重复 如果需要,现在将空间移动到索引1,并使用
2
交换。然后将空间移动到索引2,并使用
3
交换。重复此操作,直到排序完成


创建查找数组的总时间为N,每个元素交换2次,总时间为O(3N)。

您描述的算法非常正确,但您犯了几个错误

首先,您可能需要在同一位置交换多次。其次,如果您击中空格,则必须将其放置在正确的位置。这是您的循环已修复。请注意,我提前一个位置停止了迭代

for(int i = 0; i<array.length-1; i++){
    while (array[i] != i+1){
        if (space==i) {
            // it's the space
            swap(array, i, array.length-1);
            space = array.length-1;
        } else {
            swap(array, array[i]-1, space);
            space = array[i]-1;
            swap(array, space, i);
            space = i;
        }
    }
}

尽管我们添加了一个内循环,但理解为什么仍然是O(n)是很重要的:内循环的每次迭代都会精确地确定一个数字的位置,之后我们将不再移动该数字。这最多可能发生n次,因为只有那么多的数字需要修正。

“给定整数1,2,3,…,N的数组A”
,听起来数组不能包含负整数,但在测试用例中(
[7,3,5,4,6,1,2,-1]
),您使用的是负整数。输入数组可以包含负整数和正整数,还是仅包含正整数?-1表示空格字符,它不是数组中的整数,数组大小为N+1,仅包含1,2,3,…,N,-1(空格)如何,我不允许创建另一个数组,仅使用“”。我认为它必须放在适当的位置,加上计数排序中的一些步骤在这里是多余的,比如计算范围内每个数字的多重性,因为它显然是1。当你使用
N
作为空间时,为什么还要声明一个
space
变量?@Holger不幸的是,我听不懂你说的。你说
swap(array,currentNum,N);
现在,空格位于位置
currentNum
。那么,为什么我们不能
交换(array,i,currentNum);
?这取决于“space”的含义。通常,“space”是一个位置,而不是一个数值。你似乎认为空间是你移动到位置的值<代码> CurrutnUn/Case>,但是与你自己的评论相矛盾,然后用注释“<代码>交换当前项目与其位置< /代码>”。。无论如何,您的代码的实际问题已经由描述过了。您声明一个根本不用的变量
space
。@Holger感谢您提供了额外的
space
variable。无论如何,
将当前项与其位置互换
是通过提供的示例解释的。我的意思是互换<代码> 3 第三位是当前的空间。我宁愿使用<代码>交换(数组、当前对象、数组、长度-1);交换(数组、i、数组、长度-1);交换(数组、当前对象、数组、长度-1);< /COD>考虑“空间”为位置(<代码>数组>长度-1 < /代码>)它当前包含的不是值。但是…这仍然是
O(n)
?@Holger您的第二次交换会破坏OP的ru吗