【问题标题】:Stumped: Detect identical sequence of integers in two integer arraysStumped:检测两个整数数组中相同的整数序列
【发布时间】:2012-12-05 04:14:05
【问题描述】:

首先,我是一个java新手。我一直在寻找一种不涉及列表或哈希表的简洁方法来解决这个问题,但还没有找到:

**请注意,这不是家庭作业,而是“构建 Java 程序”第 7 章中的练习 #14

编写一个名为 contains 的方法,该方法接受两个整数数组作为参数,并返回一个布尔值指示第二个数组的元素是否出现在第一个数组中。

例子:

Integer[] list1 = {1,6,2,1,4,1,2,1,8};

Integer[] list2 = {1,2,1};

调用contains(list1, list2) 将返回true。我得到了可以遍历数组的嵌套 for 循环的想法,但我看不到明确的解决方案:

public static Boolean contains(Integer[] listOfNumbers1, Integer[] listOfNumbers2){

    for(int i = 0 ; i < listOfNumbers2.length; i++){

        for(int j = 0 ; j < listOfNumbers1.length; j++){

        }
    }

    return true;
}

【问题讨论】:

  • 您首先需要决定是否要搜索序列(如标题中所述)或作为集合进行比较 - 仅在第一个集合中存在第二个集合的所有元素(似乎在任务中)。代码会有很大的不同。

标签: java arrays compare


【解决方案1】:

(您并没有真正指定是否需要考虑重复项,从您的示例来看,您似乎正在尝试查看 array1 是否按顺序包含 array2 的所有元素)

有几种不同的情况需要考虑:

1. array2 is longer than array1:
       if this is the case the result must be false because array1 can't 
       possibly have the same elements in order since array2 is longer

2. array2 is the same size as array1: 
       for this step you can use a single loop and compare the elements in order, 
       if you find a  mismatch then array1 does not contain array2

       for i from 0 to length do
           if array1[i] != array2[i]
              // false
           end
       end
       // true

3. array2 is shorter than array1:
       for this case you need to examine every array2.length elements from array1 
       and see if they match array2

       matches = 0
       for i from 0 to array1.length do
           for j from 0 to array2.length do
               if array1[i] == array2[j] 
                  // increment i
                  // increment matches
               end
           end
           if matches == array2.length
               // true
           else
               // false
           end
           matches = 0  // reset matches
       end

【讨论】:

  • +1。关于序列匹配的好文章。请注意,当您超越基本时,该问题有更多的最佳解决方案 - 搜索“子字符串搜索算法”。
  • @AlexeiLevenkov 是的,我考虑过是否链接到更复杂的匹配算法,例如 Warshall 或 Floyd,但我决定不这样做,因为这似乎是一个更具介绍性的问题。不过,指出它是个好主意,谢谢,我会进行编辑。
  • #1 和 #2 是 #3 的特例,其中外循环将分别进行 0 次或 1 次迭代。我会说没有任何性能可以提高,并且通过将案例分开会失去很多清晰度。
  • @Amadan 我只是想勾勒出一些伪代码来帮助 OP 朝着正确的方向发展,但正如你所说,它们可以组合成一个嵌套的 for。
【解决方案2】:

所以基本上我们要遍历搜索数组中的每个位置 (listOfNumbers1) 并检查它是否是我们正在寻找的序列的开始 (listOfNumbers2)

// Loops through the search array
for( int i = 0; i < listOfNumbers1.length; i++ )
{
    boolean found = true;
    for(int j = 0; j < listOfNumbers2.length; j++ )
    {
        /* Check if the following conditions hold
           - Not going to cause an ArrayIndexOutOfBoundsException
           - Values do **not** match => set found to false */
        if( i+j < listOfNumbers1.length && listOfNumbers1[i + j] != listOfNumbers2[j] )
        {
            // Didn't find the sequence here
            found = false;
        }
    }

    // If found is still true, we have found the sequence and can exit
    if( found ) return true;
}

return false;

【讨论】:

  • 更高效;将 found=false 更改为 return false 并删除标志。当您已经失败时,比较其余元素是没有意义的。最后的return false 应该是return (listOfNumbers1.length!=0 || listOfNumbers2.length==0)
  • 正确,但我不想让仍在学习如何解决问题的 OP 感到困惑。一旦她/他发现优化是可能的
  • 另外,您可以循环 i 直到第一个长度减去第二个长度;如果只剩下 3 个字符,则不会找到 5 个字符的序列。这消除了每个周期的内部长度检查。
  • @ose:这不是“优化”;它避免了性能错误。
  • @SoftwareMonkey 这是一本书的学习示例,OP正在逐步学习。你当然是正确的,这是没有争议的。我要说的是,OP 正在努力理解如何概念化这个问题。解决这个问题的第一步是了解如何构建前瞻内循环。只有理解了这一点,你才能去应用你建议的“改进”
【解决方案3】:
class contains{
    public static void main(String[] args){
        int[] list1 = {1,6,2,1,4,1,2,1,8};
        int[] list2 = {1,2,1};

        if(contains(list1, list2)){
            System.out.println("list2 found in list1");
        }
        else {
            System.out.println("list2 not found in list1");
        }
    }

    public static boolean contains(int[] listOfNumbers1, int[] listOfNumbers2){
        if(listOfNumbers2.length > listOfNumbers1.length){
            return false;
        }
        for(int j = 0 ; j < listOfNumbers1.length - listOfNumbers2.length + 1; j++){
            for(int i = 0 ; i < listOfNumbers2.length; i++){
                if(listOfNumbers1[j+i] != listOfNumbers2[i]){
                    break;
                }
                else {
                    if(i == listOfNumbers2.length-1){
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

【讨论】:

  • -1。如果您对第二个数组的大小进行硬编码,为什么不再进一步硬编码整个答案 - return true 是给定常量输入的更短/更安全的版本。
  • @AlexeiLevenkov 你是对的 - 显然我太累了,无法回答问题。我将我的答案固定为可变长度,我要去睡觉了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 2023-02-09
  • 2017-11-02
  • 2019-05-03
相关资源
最近更新 更多