我在学校的计算机科学课上,我一直坚持这个问题。并且甚至不能真正想出如何解决它。
这是一字不差的:
编写一个名为contains
的静态方法,它接受两个整数数组a1和a2作为参数,并返回一个布尔值,表示a2的元素序列是否出现在a1中(true表示是,false表示否)。 a2中的元素序列可以出现在a1中的任何位置,但必须以相同的顺序连续出现。例如,如果名为list1和list2的变量存储以下值:
int[] list1 = {1, 6, 2, 1, 4, 1, 2, 1, 8};
int[] list2 = {1, 2, 1};
然后contains(list1, list2)
的调用应返回true,因为list2的值{1, 2, 1}
序列包含在list1中的list1中。如果list2存储了值{2, 1, 2}
, contains(list1, list2)
的调用将返回false,因为list1不包含该值序列。任何两个具有相同元素的列表都被认为是相互包含的,因此contains(list1, list1)
之类的调用应该返回true。
您可以假设传递给您的方法的两个数组的长度至少为1.您可能不会使用任何字符串来帮助您解决此问题,也不会使用生成字符串的方法,例如Arrays.toString。
如果有人能指出我正确的方向,那就太好了。
这也是我想出的一次尝试,但它没有足够数量的测试
public static boolean contains(int[] set1, int[] set2) {
boolean contains = false;
for (int i = 0; i < set1.length; i++) {
for (int a = 0; a < set2.length - 1; a++) {
if (set1[i] == set2[a] && set1[i + 1] == set2[a + 1]) {
contains = true;
} else {
contains = false;
}
}
}
return contains;
}
答案 0 :(得分:3)
连续
public static boolean contains(int[] set1, int[] set2) {
OUTER:
for (int i = 0; i < set1.length - set2.length; i++) {
for (int j = 0; j < set2.length; j++) {
if (set1[i + j] != set2[j])
continue OUTER;
}
return true;
}
return false;
}
要避免使用标签,您可以使用更清晰的方法
public static boolean contains(int[] set1, int[] set2) {
for (int i = 0; i < set1.length - set2.length; i++)
if (!matches(set1, i, set2))
return false;
return true;
}
public static boolean matches(int[] set1, int off, int[] set2) {
for (int j = 0; j < set2.length; j++)
if (set1[off + j] != set2[j])
return false;
return true;
}
如果只需要按顺序
public static boolean contains(int[] set1, int[] set2) {
for (int i = 0, j = 0; i < set1.length; i++)
if (set1[i] == set2[j])
if (++j >= set2.length)
return true;
return false;
}
答案 1 :(得分:3)
这是一种递归方式:
public static boolean contains(int[] set1, int[] set2) {
//System.out.println(Arrays.toString(set1) + " " + Arrays.toString(set2));
//set 2 cannot be contained within set 1 because there aren't
//enough elements. This either means that we recursed too deep
//within the first set that there are not enough elements, or
//there were not enough elements to begin with.
if (set1.length < set2.length) return false;
//from the start of each set, count the number of matches in order
int numMatched = 0;
while (numMatched < set2.length && set1[numMatched] == set2[numMatched]) {
numMatched++;
}
if (numMatched == set2.length)
//the number of matches found equals the length of the set to
//search for, so we have found a match. Return true to unravel
//the recursion.
return true;
else {
//we didn't find a match, so shift the array by 1 and then
//recursively call this function to compare again.
int[] subset = Arrays.copyOfRange(set1, 1, set1.length);
return contains(subset, set2);
}
}
每次我们找不到匹配的序列时,我们创建一个数组的子集,排除第一个元素,然后将其传递回contains来继续检查。这是每次迭代的输出:
第一次:set1 = [1,6,2,1,4,1,2,1,8]和set2 = [1,2,1] 在数组的开头没有找到匹配(我们在比较6和2时突破。下一个递归调用是这样的:
SET1 = [6,2,1,4,1,2,1,8],[1,2,1]
下一次递归比较[2,1,4,1,2,1,8] [1,2,1]
等等,直到最后的递归比较: [1,2,1,8] [1,2,1]并按顺序找到匹配。
答案 2 :(得分:2)
从int first=list2[0];
开始,然后在list1
中找到该号码。接下来,循环遍历list2
中的所有值,同时从先前找到的位置循环list1
,直到list2
中验证整个list1
或找到差异为止。如果发现差异,请在之前找到的位置后使用first
重新启动。
通过调整无耻地复制另一个答案:
public static boolean contains(int[] set1, int[] set2) {
for (int i = 0, j = 0; i < set1.length; i++) {
if (set1[i] == set2[j]) {
if (++j >= set2.length)
return true;
}
else {
i -= j;
j = 0;
}
}
return false;
}
此连续版本机制还确保在没有任何额外检查的情况下不会发生超支。
答案 3 :(得分:2)
我会说,就心态而言,你应该认为“在匹配之前对数组起作用的第一个元素”。
public static boolean contains(int[] set1, int[] set2) {
for (int i = 0; i < set1.length; i++) {
int count = 0;
for (int w = 0; w < set2.length; w++) {
if (set2[w] == set1[i + w]) {
count++;
} else {
count = 0;
continue;
}
}
if (count == set2.length) {
return true;
}
}
return false;
从这个意义上说,你只会在你的第二个阵列上向前推进,以便根据需要进行比较。如果在浏览set2
中的所有元素后,您最终得到相同的长度,那么它就包含在set1
中。当然,问你是否有问题:)
答案 4 :(得分:2)
Demo of this answer at IDEOne.com
我想出了以下功能。阅读评论以了解其背后的逻辑:
public static boolean contains(int[] a, int[] b) {
//Loop until there aren't enough elements left in a to match b.
for (int i = 0; i < a.length - b.length + 1; i++) {
for (int j = 0; j < b.length; j++) {
//If the jth element of b doesn't match
//the corresponding element of a, then move
//to the next step in the sequence.
if (a[i + j] != b[j])
break;
//If we are at the end of the loop, return
//true because that means we found a consecutive match.
if (j == b.length - 1)
return true;
}
}
return false; //If we got here, there are no matches.
}
答案 5 :(得分:1)
我考虑过这个并提出了这个解决方案:
static boolean contains(final int[] list1, final int[] list2) {
final int limit = list1.length - list2.length + 1; // we do not need to check an index >= limit, because list2 wouldn't fit anymore at this point
for (int indexL1 = 0, indexL2 = 0; indexL1 < limit; ++indexL1) {
while (list1[indexL1 + indexL2] == list2[indexL2]) { // check all matches from here
++indexL2;
if (indexL2 == list2.length) { // if all of list2 matched so far, we found it
return true;
}
}
indexL2 = 0; // we did not find it, start from beginning of list2 again
}
return false; // no match found
}
我称之为Lawrey-Solution。