例如,如果我传入数字,则传递数组2, 3, 3, 3, 1
。它删除了重复的3,但为什么呢?结果是123(由于排序方法,它应该是这样的)。
Sortering.sorterHeltallstabell(tab)
只是对我的代码进行排序,而其余的则删除重复的代码。它会在删除重复项之前进行排序。
为什么在将代码传递给方法时,此代码会删除数组的重复项?
public static int[] utenDubletter(int[] tab){
Sortering.sorterHeltallstabell(tab);
if (tab.length < 2)
return tab;
//why does this code remove duplicates?
int j = 0;
int i = 1;
while (i < tab.length) {
if (tab[i] == tab[j]) {
i++;
} else {
j++;
tab[j] = tab[i];
i++;
}
}
int[] B = Arrays.copyOf(tab, j + 1);
return B;
}
答案 0 :(得分:3)
挖掘这个模拟:
Start
[1, 1, 1, 2, 2, 2, 3]
j i
Duplicate found (tab[i] == tab[j]), move i over 1 (i++)
[1, 1, 1, 2, 2, 2, 3]
j i
Duplicate found, move i over 1
[1, 1, 1, 2, 2, 2, 3]
j i
Non-duplicate (else); adding 1 to j (j++),
copying element i to el j (tab[j] = tab[i]),
adding 1 to i (i++)
[1, 2, 1, 2, 2, 2, 3]
j i
Duplicate found, move i over 1
[1, 2, 1, 2, 2, 2, 3]
j i
Duplicate found, move i over 1
[1, 2, 1, 2, 2, 2, 3]
j i
Non-duplicate; adding 1 to j, copying i to j, adding 1 to i
[1, 2, 3, 2, 2, 2, 3]
j i
i == tab.length, so stop
Copy first 3 elements of array (up to j) to result
(int[] B = Arrays.copyOf(tab, j + 1)) and return it
答案 1 :(得分:3)
这是因为
下的代码if (tab[i] == tab[j])
遍历排序的数组,跳过重复的元素,然后将每个唯一元素向前复制到数组的前部,就在已经扫描过的(并且已知是唯一元素)之后。然后它只保留数组的前部。
单步执行代码:
if (tab.length < 2)
return tab;
int j = 0;
int i = 1;
方法得到输入:[1,1,1,2,2,2,3],是排序的(因为输入已经在这个例子中排序,没有变化),tab大于2,所以做不回来 j被赋值为0 我被分配了值1
while (i < tab.length) { ... }
i(即1)小于标签长度(即7)。输入循环时:
if (tab[i] == tab[j]) {
i++;
} else {
j++;
tab[j] = tab[i];
i++;
}
迭代1: tab [i],即tab [1],它是1,与tab [j]进行比较,tab [j]是tab [0],它是1.它们相等,所以i递增。我现在2岁。
迭代2: tab [i](tab [2]或1)与tab [j](tab [0]或1)进行比较。他们是平等的,所以我增加了。我现在3岁。
迭代3: tab [i](tab [3]或2)与tab [j](tab [0]或1)进行比较。他们不平等。 j递增,现在为1. tab [j](tab [1])被赋值tab [i](tab [3])的值。 tab现在是[1,2,1,2,2,2,3]。我增加了,现在是4。
迭代4: tab [i](tab [4]或2)与tab [j](tab [1]或2)进行比较。他们是平等的,所以我增加了。我现在5岁。
迭代5: tab [i](tab [5]或2)与tab [j](tab [1]或2)进行比较。他们是平等的,所以我增加了。我现在6岁。
迭代6: tab [i](tab [6]或3)与tab [j](tab [1]或2)进行比较。他们不平等。 j递增,现在为2. tab [j](tab [2])被赋值tab [i](tab [6])的值。选项卡现在是[1,2,3,2,2,2,3]。我增加了,现在是7。
我现在不再小于tab的长度,我们退出while循环。
int[] B = Arrays.copyOf(tab, j + 1);
return B;
通过从第一个元素开始将制表符复制到长度j + 1或3来创建B. B现在是[1,2,3]。
方法按预期返回[1,2,3]。
答案 2 :(得分:2)
很明显,用行
if (tab[i] == tab[j])
如果两个连续元素相同,则可以跳过数组的元素。
答案 3 :(得分:2)
对于此代码的重复删除部分,有一些重要的注意事项。
实际上,在确定重复项的过程中会覆盖数组的内容。它使用数组的前部(先前已经检查过)来存储非重复项的内容。由于Java按值传递对象(特别是引用值),因此对参数的本地副本的更改不会在调用方法中传播回来。对于通过引用传递对象的语言(如C#),情况并非如此,因此该算法无法在那里工作。
此算法取决于对数组进行排序的事实将所有相同的副本放入单个连续的索引块中。这可以保证所有未来的元素永远不会匹配以前在多次迭代之前被覆盖的东西(因为它至少是当前最大值的大小,否则数组实际上没有正确排序)。
高度评论解释
public static int[] utenDubletter(int[] tab){
//sort the array
Sortering.sorterHeltallstabell(tab);
//There must be at least 2 elements for any duplicate to exist
if (tab.length < 2)
return tab;
int j = 0; //index of the largest element in the new array found so far
int i = 1; //index of the current index of the array being checked
while (i < tab.length) {
//if it's a duplicate
if (tab[i] == tab[j]) {
i++; //just skip this element and check the next one
} else {
j++; //since this number does not exist in the new array make space for it
tab[j] = tab[i]; //record this new element
//we have checked this element (with i) before this
//so we don't need to keep it around any longer
i++; //move onto the next element
}
}
int[] B = Arrays.copyOf(tab, j + 1); //copy only the elements that we actually
//manually overwrote. Since arrays are
//0-indexed, add one to the final index (j)
//for the number of elements in our new array.
return B;
}