如何检查两个数组(循环)是否具有相同顺序的元素。例如,让我们来看看数组[1,2,3,4]。检查两个数组是否具有相同顺序的元素
该测试应该为[2,3,4,1],[3,4,1,2],[4,1,2,3]返回true,但不适用于[1,3,2,4 ],[1,4,2,3]或[1,2,3,5]。
我最初的做法是找到第一个匹配 - 每个数组中的一个元素是相等的 - 并将这两个元素作为它们各自数组的初始元素,我将逐个比较剩余的数组元素。
有没有更好的方法? 谢谢。
如何检查两个数组(循环)是否具有相同顺序的元素。例如,让我们来看看数组[1,2,3,4]。检查两个数组是否具有相同顺序的元素
该测试应该为[2,3,4,1],[3,4,1,2],[4,1,2,3]返回true,但不适用于[1,3,2,4 ],[1,4,2,3]或[1,2,3,5]。
我最初的做法是找到第一个匹配 - 每个数组中的一个元素是相等的 - 并将这两个元素作为它们各自数组的初始元素,我将逐个比较剩余的数组元素。
有没有更好的方法? 谢谢。
如果一个数组是循环的,那么array+array
就是整个数组的另一部分。 例如:
[2 3 4 1] append [2 3 4 1] = [2 3 4 1 2 3 4 1]
|-------|
,你可以看到[1 2 3 4]
是“某处”在同一个阵列的追加两倍。
因此,通过这个逻辑,你可以做一个O(n*m)
操作,检查每一种情况下,看它是否匹配(n为数组1和m为数组2):
//array1 has [2 3 4 1 2 3 4 1]
//array2 has [1 2 3 4]
boolean check = false;
for(int i = 0; i < array1.length(); i++) {
for(int j; j < array2.length(); j++) {
if((i+j) <= array1.length()) {
if(array1[i+j] == array2[j])
check = true;
else
check = false;
}
}
if(check)
return true; // returns true if all array2 == some part of array1
}
return false;
您还可以检查出Boyer-Moore algorithm到改善这一点。它用于字符串匹配,但是可以在这里应用相同的逻辑。
基本思想是有一个array2查找表,并能够“跳过”你知道你不必再次检查的值。
1 2 3 4 5 6
3 4 5
^-------^ lookup table sees that the offset is 3 to match array2[0] with array1[2]
1 2 3 4 5 6
skip to--->3 4 5
would be the next iteration
非常感谢。你的解释确实对我有帮助,正是我所需要的。出于好奇,我的老师提到循环数组有特殊的性质,可以在线性时间内检查这种相等性。你知道这件事吗? – 2014-11-06 00:50:19
原始数组中是否有重复值?实际上这个算子不是0(n^2)我认为我犯了一个错误,它实际上是0(n * m),其中n是第一个数组,m是第二个数组。随着n的增加,分摊时间变为0(n)。我还在底部添加了一些东西来使此算法更快 – Jay 2014-11-06 01:07:47
在我的问题中不应该有任何重复。但在老师提到的问题上,我不确定。他总体上说2个循环数组。改进的算法应该是O(3n)。 – 2014-11-06 10:31:46
假设这个算法可以帮助你。
public void test() {
int[] a1 = {1,2,3,4};
int[] a2 = {2,3,4,5};
int[] a3 = {2,3,4,1};
if (calculateDifference(a1, a2)) {
System.out.println("a1 has same elements order to a2");
}
if (calculateDifference(a1, a3)) {
System.out.println("a1 has same elements order to a3");
}
if (calculateDifference(a2, a3)) {
System.out.println("a2 has same elements order to a3");
}
}
private boolean calculateDifference(int[] a1,int[] a2){
int total = 0;
boolean match = false;
if (a1.length != a2.length) {
return match;
}
for (int i = 0; i < a1.length; i++) {
int a1Num = a1[i];
int a2Num = a2[i];
total += a1Num - a2Num;
}
if (total == 0) {
match = true;
}
return match;
}
该算法不考虑元素的顺序。 EG:'calculateDifference(new int [] {1,3,2,4},new int [] {1,2,3,4})''是'true'。应该是'false' – 2014-11-06 00:32:49
乔说{1,3,2,4}应该是错误的,因为它的顺序不一样。 – 2014-11-06 02:26:54
如果没有允许重复你只需要找到第二阵列中等于第一第一阵列的另一个元件,并从那里检查它们,溶液是O(n):
boolean areEquivalent(int[] array1, int[] array2) {
int i1 = 0, i2 = 0;
for (; i2 < array2.length; ++i2)
if (array2[i2] == array1[i1])
break;
// no element found in common, they can't be equivalent
if (i2 == array2.length)
return false;
for (int j = 0; j < array1.length; ++j)
if (array1[i1+j] != array2[(i2+j) % array2.length]
return false;
return true;
}
如果允许重复,您必须考虑到i1
和i2
可以从不同的点开始并尝试所有这些,如果最后的for
失败,则应该将i1
更改为从第二次出现相同值开始,依此类推。完成此操作后,您必须再次更改i2
e,因此不同的方法(如Jay提议的方法)会更好。
我已经试过这样的,它的工作原理:
int a[] = {2,3,4,1};
int b[] = {3,4,1,2}; // return true for these input
boolean check = false;
for (int i = 0; i < a.length; i++) {
int tmp = b[0];
System.arraycopy(b, 1, b, 0, b.length - 1);
b[b.length - 1] = tmp;
if (Arrays.equals(a, b)) {
check = true;
System.out.println("Output: " + Arrays.equals(a, b));
}
}
if (!check) {
System.out.println("Output: false");
}
是否允许重复?没有重复,它是相当微不足道的,重复是微不足道的,但不太明显。 – Jack 2014-11-06 00:18:23
你的方法是一个好的开始,但它会失败'[1,2,1,3]'和'[1,3,1,2]'。只要将第一个视为无尽的重复,并在第二个子索引中进行搜索(限于索引0到N) – 2014-11-06 00:19:51