检查该序列是否是另一个序列的子序列

时间:2019-02-02 18:30:55

标签: c#

有号码的两个序列。检查第二个序列是否是第一个序列的子序列。如果存在数字0≤i_0

输入:

的整数数组:

  1. 第一序列的部件的数量。

  2. 第一个序列的成员。

  3. 第二序列的部件的数量。

  4. 第二个序列的成员。

输出:

一个整数:

·任一个,如果所述第二序列是第一序列的子序列,

·或为零。

我的解决方案:

class Program
{
    static void Main(string[] args)
    {
        var input = Console.ReadLine();
        var numbers = input.Split(' ').Select(x => int.Parse(x)).ToArray();
        int a = numbers[0];
        int[] arr1 = numbers.Skip(1).Take(a).ToArray();
        int b = numbers.Skip(a + 1).Take(1).ToArray()[0];
        int[] arr2 = numbers.Skip(a + 2).Take(b).ToArray();
        if(arr1.Length==0 || arr2.Length==0) Console.Write("0");
        else Console.Write(contains(arr1, arr2));
    }

    private static int contains(int[] arr1, int[] arr2)
    {
        int check = 1;
        int[] checkArray = arr1;
        for(int i=0;i<arr2.Length;i++)
        {
            if (!checkArray.Contains(arr2[i])) return 0;
            checkArray = checkArray.Skip(Array.FindIndex(checkArray, x => x==arr2[i])).ToArray();
        }
        return check;
    }

它运行在自动测试器,并在每个睾丸中返回正确的结果,除了一个一个。我不知道此测试的输入数据是什么,我也找不到它。什么会导致这种问题,什么将是解决方案?

UPD:任务描述中的示例 范例:

输入:5 1 2 3 4 5 2 1 4

输出:1

输入:5 1 2 3 4 5 2 4 1

输出:0

3 个答案:

答案 0 :(得分:0)

这将返回1:3 1 2 3 3 1 1 3

  1. 第一个数组长度:3
  2. 第一个数组:1 2 3
  3. 第二个数组长度:3
  4. 第二个数组:1 1 3

在第二阵列不应该由你的定义的子序列。我想原因是FindIndex返回一个0的索引,所以你Skip应该加1后,返回的值跳过正确的号码。

您也不需要同时执行ContainsFindIndex。如果没有索引,FindIndex将返回-1,这样可以防止不必要的数组迭代。它也有一个重载需要的范围内,所以你不需要使用skip并搜索take。参见文档here

答案 1 :(得分:0)

哦!我有同样的问题))我找到了解决方案!在c ++上正确的版本

#include <iostream>
#include <vector>
#include <stdio.h>
#include <string>
#include <sstream>

using namespace std;
int main()
{
    int len, len2, t=0, i=0;

    std::string sentence;
    std::cout.flush();

    std::getline(std::cin,sentence);
    std::istringstream iss(sentence);

    std::vector<double> words;
    std::vector<double> SubSeq;

    vector<double>::iterator it;
    double word;
    while(iss >> word)
    {
        words.push_back(word);
    }
    len= static_cast<int>(words.front());
    it = words.begin();
    words.erase(it);
    words.shrink_to_fit();

    for( i=len; i<words.size(); i++ )
    {
           SubSeq.insert(SubSeq.end(),words[i]);
    }
    it = words.begin()+len;
    words.erase(it,words.end());
    words.shrink_to_fit();


    len2= static_cast<int>(SubSeq.front());
    it = SubSeq.begin();
    SubSeq.erase(it);
    SubSeq.shrink_to_fit();

    int j;
    for(i=0 , j=0; i<len && j<len2; i++ )
    {
        if( SubSeq[j]== words[i]){
            j++;
        }
    }

    if( j == len2)
        cout<<1;
    else
        cout<<0;
  return 0;
}

我更改了这部分

/*
 i=0;
        for(it=words.begin(); it!=words.end(); it++ )
        {
            if( SubSeq[i]== *it){
                i++;    
        }
*/

并粘贴

for(i=0 , j=0; i<len && j<len2; i++ )
        {
            if( SubSeq[j]== words[i]){
                j++;
            }

答案 2 :(得分:0)

此问题的核心逻辑是期待通过这两个序列。在第二个序列的第一个序列中找到下一个元素的实例时,可以在第一个序列中前进。您缺少的关键步骤是,找到匹配项时,需要通过增加其迭代器来“消耗”第二个元素。

checkArray = checkArray.Skip(Array.FindIndex(checkArray, x => x==arr2[i])).ToArray();

checkArray返回0时,此行不会更改FindIndex的内容,因此您可以在第一个元素上保持匹配。结果,您的算法将报告“ 2 2 2 2”是“ 1 2 3”的子字符串。

我通常是Linq扩展的粉丝,但是我认为它确实使这里的代码感到困惑。我只是写一个循环来处理数组。

相关问题