📜  最长连续子序列

📅  最后修改于: 2021-05-04 07:41:18             🧑  作者: Mango

给定整数数组,请找到最长子序列的长度,以使子序列中的元素为连续整数,连续数字可以采用任何顺序。

例子

Input: arr[] = {1, 9, 3, 10, 4, 20, 2}
Output: 4
Explanation: 
The subsequence 1, 3, 4, 2 is the longest 
subsequence of consecutive elements

Input: arr[] = {36, 41, 56, 35, 44, 33, 34, 92, 43, 32, 42}
Output: 5
Explanation: 
The subsequence 36, 35, 33, 34, 32 is the longest 
subsequence of consecutive elements.

天真的方法:想法是首先对数组进行排序,然后找到具有连续元素的最长子数组。
在对数组进行排序并删除了多次出现的元素之后,运行一个循环并保留一个count和max(最初都为零)。从头到尾运行一个循环,如果当前元素不等于前一个元素(元素+1),则将计数设置为1,否则增加计数。用最大数量和最大数量更新最大数量。

C++
// C++ program to find longest
// contiguous subsequence
#include 
using namespace std;
 
// Returns length of the longest
// contiguous subsequence
int findLongestConseqSubseq(int arr[], int n)
{
    int ans = 0, count = 0;
 
    // sort the array
    sort(arr, arr + n);
 
    vector v;
    v.push_back(arr[0]);
 
    //insert repeated elements only once in the vector
    for (int i = 1; i < n; i++)
    {
        if (arr[i] != arr[i - 1])
            v.push_back(arr[i]);
    }
    // find the maximum length
    // by traversing the array
    for (int i = 0; i < v.size(); i++)
    {
         
        // Check if the current element is equal
        // to previous element +1
        if (i > 0 && v[i] == v[i - 1] + 1)
            count++;
        // reset the count
        else
            count = 1;
 
        // update the maximum
        ans = max(ans, count);
    }
    return ans;
}
 
// Driver code
int main()
{
    int arr[] = { 1, 2, 2, 3 };
    int n = sizeof arr / sizeof arr[0];
    cout << "Length of the Longest contiguous subsequence "
            "is "
         << findLongestConseqSubseq(arr, n);
    return 0;
}


Java
// Java program to find longest
// contiguous subsequence
import java.io.*;
import java.util.*;
 
class GFG
{
 
    static int findLongestConseqSubseq(int arr[],
                                           int n)
    {
 
        // Sort the array
        Arrays.sort(arr);
 
        int ans = 0, count = 0;
       
        ArrayList v = new ArrayList();
        v.add(10);
       
        // Insert repeated elements
        // only once in the vector
        for (int i = 1; i < n; i++)
        {
            if (arr[i] != arr[i - 1])
                v.add(arr[i]);
        }
    
 
        // Find the maximum length
        // by traversing the array
        for (int i = 0; i < v.size(); i++)
        {
 
            // Check if the current element is
            // equal to previous element +1
            if (i > 0 &&v.get(i) == v.get(i - 1) + 1)
                count++;
            else
                count = 1;
 
            // Update the maximum
            ans = Math.max(ans, count);
        }
        return ans;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
        int n = arr.length;
 
        System.out.println(
            "Length of the Longest "
            + "contiguous subsequence is "
            + findLongestConseqSubseq(arr, n));
    }
}
 
// This code is contributed by parascoding


Python3
# Python3 program to find longest
# contiguous subsequence
 
# Returns length of the longest
# contiguous subsequence
def findLongestConseqSubseq(arr, n):
     
    ans = 0
    count = 0
 
    # Sort the array
    arr.sort()
 
    v = []
 
    v.append(arr[0])
 
    # Insert repeated elements only
    # once in the vector
    for i in range(1, n):
        if (arr[i] != arr[i - 1]):
            v.append(arr[i])
 
    # Find the maximum length
    # by traversing the array
    for i in range(len(v)):
 
        # Check if the current element is
        # equal to previous element +1
        if (i > 0 and v[i] == v[i - 1] + 1):
            count += 1
             
        # Reset the count
        else:
            count = 1
             
        # Update the maximum
        ans = max(ans, count)
         
    return ans
 
# Driver code
arr = [ 1, 2, 2, 3 ]
n = len(arr)
 
print("Length of the Longest contiguous subsequence is",
       findLongestConseqSubseq(arr, n))
 
# This code is contributed by avanitrachhadiya2155


C#
// C# program to find longest
// contiguous subsequence
using System;
using System.Collections.Generic;
 
class GFG{
     
static int findLongestConseqSubseq(int[] arr,
                                   int n)
{
     
    // Sort the array
    Array.Sort(arr);
 
    int ans = 0, count = 0;
    
    List v = new List();
    v.Add(10);
    
    // Insert repeated elements
    // only once in the vector
    for(int i = 1; i < n; i++)
    {
        if (arr[i] != arr[i - 1])
            v.Add(arr[i]);
    }
     
    // Find the maximum length
    // by traversing the array
    for(int i = 0; i < v.Count; i++)
    {
         
        // Check if the current element is
        // equal to previous element +1
        if (i > 0 && v[i] == v[i - 1] + 1)
            count++;
        else
            count = 1;
 
        // Update the maximum
        ans = Math.Max(ans, count);
    }
    return ans;
}
 
// Driver code
static void Main()
{
    int[] arr = { 1, 9, 3, 10, 4, 20, 2 };
    int n = arr.Length;
 
    Console.WriteLine("Length of the Longest " +
                      "contiguous subsequence is " +
                      findLongestConseqSubseq(arr, n));
}
}
 
// This code is contributed by divyeshrabadiya07


C++
// C++ program to find longest
// contiguous subsequence
#include 
using namespace std;
 
// Returns length of the longest
// contiguous subsequence
int findLongestConseqSubseq(int arr[], int n)
{
    unordered_set S;
    int ans = 0;
 
    // Hash all the array elements
    for (int i = 0; i < n; i++)
        S.insert(arr[i]);
 
    // check each possible sequence from
    // the start then update optimal length
    for (int i = 0; i < n; i++)
    {
        // if current element is the starting
        // element of a sequence
        if (S.find(arr[i] - 1) == S.end())
        {
            // Then check for next elements
            // in the sequence
            int j = arr[i];
            while (S.find(j) != S.end())
                j++;
 
            // update  optimal length if
            // this length is more
            ans = max(ans, j - arr[i]);
        }
    }
    return ans;
}
 
// Driver code
int main()
{
    int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
    int n = sizeof arr / sizeof arr[0];
    cout << "Length of the Longest contiguous subsequence "
            "is "
         << findLongestConseqSubseq(arr, n);
    return 0;
}


Java
// Java program to find longest
// consecutive subsequence
import java.io.*;
import java.util.*;
 
class ArrayElements {
    // Returns length of the longest
    // consecutive subsequence
    static int findLongestConseqSubseq(int arr[], int n)
    {
        HashSet S = new HashSet();
        int ans = 0;
 
        // Hash all the array elements
        for (int i = 0; i < n; ++i)
            S.add(arr[i]);
 
        // check each possible sequence from the start
        // then update optimal length
        for (int i = 0; i < n; ++i)
        {
            // if current element is the starting
            // element of a sequence
            if (!S.contains(arr[i] - 1))
            {
                // Then check for next elements
                // in the sequence
                int j = arr[i];
                while (S.contains(j))
                    j++;
 
                // update  optimal length if this
                // length is more
                if (ans < j - arr[i])
                    ans = j - arr[i];
            }
        }
        return ans;
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
        int n = arr.length;
        System.out.println(
            "Length of the Longest consecutive subsequence is "
            + findLongestConseqSubseq(arr, n));
    }
}
// This code is contributed by Aakash Hasija


Python
# Python program to find longest contiguous subsequence
 
from sets import Set
 
 
def findLongestConseqSubseq(arr, n):
 
    s = Set()
    ans = 0
 
    # Hash all the array elements
    for ele in arr:
        s.add(ele)
 
    # check each possible sequence from the start
    # then update optimal length
    for i in range(n):
 
         # if current element is the starting
        # element of a sequence
        if (arr[i]-1) not in s:
 
            # Then check for next elements in the
            # sequence
            j = arr[i]
            while(j in s):
                j += 1
 
            # update  optimal length if this length
            # is more
            ans = max(ans, j-arr[i])
    return ans
 
 
# Driver code
if __name__ == '__main__':
    n = 7
    arr = [1, 9, 3, 10, 4, 20, 2]
    print "Length of the Longest contiguous subsequence is ",
    print findLongestConseqSubseq(arr, n)
 
# Contributed by: Harshit Sidhwa


C#
using System;
using System.Collections.Generic;
 
// C# program to find longest consecutive subsequence
 
public class ArrayElements {
    // Returns length of the
    // longest consecutive subsequence
    public static int findLongestConseqSubseq(int[] arr,
                                              int n)
    {
        HashSet S = new HashSet();
        int ans = 0;
 
        // Hash all the array elements
        for (int i = 0; i < n; ++i) {
            S.Add(arr[i]);
        }
 
        // check each possible sequence from the start
        // then update optimal length
        for (int i = 0; i < n; ++i)
        {
            // if current element is the starting
            // element of a sequence
            if (!S.Contains(arr[i] - 1))
            {
                // Then check for next elements in the
                // sequence
                int j = arr[i];
                while (S.Contains(j))
                {
                    j++;
                }
 
                // update  optimal length if this length
                // is more
                if (ans < j - arr[i])
                {
                    ans = j - arr[i];
                }
            }
        }
        return ans;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int[] arr = new int[] { 1, 9, 3, 10, 4, 20, 2 };
        int n = arr.Length;
        Console.WriteLine(
            "Length of the Longest consecutive subsequence is "
            + findLongestConseqSubseq(arr, n));
    }
}
 
// This code is contributed by Shrikant13


C++
// CPP program for the above approach
#include 
using namespace std;
 
int findLongestConseqSubseq(int arr[], int N)
{
    priority_queue, greater > pq;
    for (int i = 0; i < N; i++) {
       
        // adding element from
        // array to PriorityQueue
        pq.push(arr[i]);
    }
 
    // Storing the first element
    // of the Priority Queue
    // This first element is also
    // the smallest element
    int prev = pq.top();
    pq.pop();
 
    // Taking a counter variable with value 1
    int c = 1;
 
    // Storing value of max as 1
    // as there will always be
    // one element
    int max = 1;
    for (int i = 1; i < N; i++) {
       
        // check if current peek
        // element minus previous
        // element is greater then
        // 1 This is done because
        // if it's greater than 1
        // then the sequence
        // doesn't start or is broken here
        if (pq.top() - prev > 1) {
           
            // Store the value of counter to 1
            // As new sequence may begin
            c = 1;
 
            // Update the previous position with the
            // current peek And remove it
            prev = pq.top();
            pq.pop();
        }
 
        // Check if the previous
        //  element and peek are same
        else if (pq.top() - prev == 0) {
           
            // Update the previous position with the
            // current peek And remove it
            prev = pq.top();
            pq.pop();
        }
       
        // If the difference
        // between previous element and peek is 1
        else {
           
            // Update the counter
            // These are consecutive elements
            c++;
 
            // Update the previous position
            //  with the current peek And remove it
            prev = pq.top();
            pq.pop();
        }
       
        // Check if current longest
        // subsequence is the greatest
        if (max < c) {
           
            // Store the current subsequence count as
            // max
            max = c;
        }
    }
    return max;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
    int n = 7;
 
    cout << "Length of the Longest consecutive subsequence "
            "is "
         << findLongestConseqSubseq(arr, n);
    return 0;
}
// this code is contributed by Manu Pathria


Java
// Java Program to find longest consecutive
// subsequence This Program uses Priority Queue
import java.io.*;
import java.util.PriorityQueue;
public class Longset_Sub
{
    // return the length of the longest
    // subsequence of consecutive integers
    static int findLongestConseqSubseq(int arr[], int N)
    {
 
        PriorityQueue pq
            = new PriorityQueue();
        for (int i = 0; i < N; i++)
        {
            // adding element from
            // array to PriorityQueue
            pq.add(arr[i]);
        }
         
        // Storing the first element
        // of the Priority Queue
        // This first element is also
        // the smallest element
        int prev = pq.poll();
         
        // Taking a counter variable with value 1
        int c = 1;
         
        // Storing value of max as 1
        // as there will always be
        // one element
        int max = 1;
 
        for (int i = 1; i < N; i++)
        {
            // check if current peek
            // element minus previous
            // element is greater then
            // 1 This is done because
            // if it's greater than 1
            // then the sequence
            // doesn't start or is broken here
            if (pq.peek() - prev > 1)
            {
                // Store the value of counter to 1
                // As new sequence may begin
                c = 1;
                 
                // Update the previous position with the
                // current peek And remove it
                prev = pq.poll();
            }
             
            // Check if the previous
            //  element and peek are same
            else if (pq.peek() - prev == 0)
            {
                // Update the previous position with the
                // current peek And remove it
                prev = pq.poll();
            }
            // if the difference
            // between previous element and peek is 1
            else
            {
                // Update the counter
                // These are consecutive elements
                c++;
                  
                // Update the previous position
                //  with the current peek And remove it
                prev = pq.poll();
            }
 
            // Check if current longest
            // subsequence is the greatest
            if (max < c)
            {
                // Store the current subsequence count as
                // max
                max = c;
            }
        }
 
        return max;
    }
     
    // Driver Code
    public static void main(String args[])
        throws IOException
    {
        int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
        int n = arr.length;
        System.out.println(
            "Length of the Longest consecutive subsequence is "
            + findLongestConseqSubseq(arr, n));
    }
}
// This code is contributed by Sudipa Sarkar


输出
Length of the Longest contiguous subsequence is 3

复杂度分析:

  • 时间复杂度: O(nLogn)。
    对数组进行排序的时间为O(nlogn)。
  • 辅助空间: O(1)。
    由于不需要额外的空间。

感谢Hao.W建议上述解决方案。

高效的解决方案:
可以使用有效解决方案在O(n)时间内解决此问题。这个想法是使用散列。我们首先将所有元素插入Set中。然后检查连续子序列的所有可能开始。

算法:

  1. 创建一个空哈希。
  2. 将所有数组元素插入到哈希中。
  3. 对每个元素arr [i]执行以下操作
  4. 检查此元素是否是子序列的起点。要检查这一点,只需在哈希中查找arr [i] – 1(如果未找到),则这是子序列的第一个元素。
  5. 如果此元素是第一个元素,则计算从该元素开始的连续元素的数量。从arr [i] + 1迭代直到找到最后一个元素。
  6. 如果计数大于以前找到的最长子序列,则更新它。

下图是上述方法的模拟:

下面是上述方法的实现:

C++

// C++ program to find longest
// contiguous subsequence
#include 
using namespace std;
 
// Returns length of the longest
// contiguous subsequence
int findLongestConseqSubseq(int arr[], int n)
{
    unordered_set S;
    int ans = 0;
 
    // Hash all the array elements
    for (int i = 0; i < n; i++)
        S.insert(arr[i]);
 
    // check each possible sequence from
    // the start then update optimal length
    for (int i = 0; i < n; i++)
    {
        // if current element is the starting
        // element of a sequence
        if (S.find(arr[i] - 1) == S.end())
        {
            // Then check for next elements
            // in the sequence
            int j = arr[i];
            while (S.find(j) != S.end())
                j++;
 
            // update  optimal length if
            // this length is more
            ans = max(ans, j - arr[i]);
        }
    }
    return ans;
}
 
// Driver code
int main()
{
    int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
    int n = sizeof arr / sizeof arr[0];
    cout << "Length of the Longest contiguous subsequence "
            "is "
         << findLongestConseqSubseq(arr, n);
    return 0;
}

Java

// Java program to find longest
// consecutive subsequence
import java.io.*;
import java.util.*;
 
class ArrayElements {
    // Returns length of the longest
    // consecutive subsequence
    static int findLongestConseqSubseq(int arr[], int n)
    {
        HashSet S = new HashSet();
        int ans = 0;
 
        // Hash all the array elements
        for (int i = 0; i < n; ++i)
            S.add(arr[i]);
 
        // check each possible sequence from the start
        // then update optimal length
        for (int i = 0; i < n; ++i)
        {
            // if current element is the starting
            // element of a sequence
            if (!S.contains(arr[i] - 1))
            {
                // Then check for next elements
                // in the sequence
                int j = arr[i];
                while (S.contains(j))
                    j++;
 
                // update  optimal length if this
                // length is more
                if (ans < j - arr[i])
                    ans = j - arr[i];
            }
        }
        return ans;
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
        int n = arr.length;
        System.out.println(
            "Length of the Longest consecutive subsequence is "
            + findLongestConseqSubseq(arr, n));
    }
}
// This code is contributed by Aakash Hasija

Python

# Python program to find longest contiguous subsequence
 
from sets import Set
 
 
def findLongestConseqSubseq(arr, n):
 
    s = Set()
    ans = 0
 
    # Hash all the array elements
    for ele in arr:
        s.add(ele)
 
    # check each possible sequence from the start
    # then update optimal length
    for i in range(n):
 
         # if current element is the starting
        # element of a sequence
        if (arr[i]-1) not in s:
 
            # Then check for next elements in the
            # sequence
            j = arr[i]
            while(j in s):
                j += 1
 
            # update  optimal length if this length
            # is more
            ans = max(ans, j-arr[i])
    return ans
 
 
# Driver code
if __name__ == '__main__':
    n = 7
    arr = [1, 9, 3, 10, 4, 20, 2]
    print "Length of the Longest contiguous subsequence is ",
    print findLongestConseqSubseq(arr, n)
 
# Contributed by: Harshit Sidhwa

C#

using System;
using System.Collections.Generic;
 
// C# program to find longest consecutive subsequence
 
public class ArrayElements {
    // Returns length of the
    // longest consecutive subsequence
    public static int findLongestConseqSubseq(int[] arr,
                                              int n)
    {
        HashSet S = new HashSet();
        int ans = 0;
 
        // Hash all the array elements
        for (int i = 0; i < n; ++i) {
            S.Add(arr[i]);
        }
 
        // check each possible sequence from the start
        // then update optimal length
        for (int i = 0; i < n; ++i)
        {
            // if current element is the starting
            // element of a sequence
            if (!S.Contains(arr[i] - 1))
            {
                // Then check for next elements in the
                // sequence
                int j = arr[i];
                while (S.Contains(j))
                {
                    j++;
                }
 
                // update  optimal length if this length
                // is more
                if (ans < j - arr[i])
                {
                    ans = j - arr[i];
                }
            }
        }
        return ans;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int[] arr = new int[] { 1, 9, 3, 10, 4, 20, 2 };
        int n = arr.Length;
        Console.WriteLine(
            "Length of the Longest consecutive subsequence is "
            + findLongestConseqSubseq(arr, n));
    }
}
 
// This code is contributed by Shrikant13
输出
Length of the Longest contiguous subsequence is 4

复杂度分析:

  • 时间复杂度: O(n)。
    在散列插入和搜索花费O(1)时间的假设下,只需要一个遍历,时间复杂度为O(n)。
  • 辅助空间: O(n)。
    要将每个元素存储在哈希图中,需要O(n)空间
    感谢Gaurav Ahirwar提供了上述解决方案。

高效的解决方案:

这个问题可以用另一种有效的方法O(n)时间内解决,这一次的想法是使用优先级队列。

算法:

  1. 创建一个优先级队列来存储元素
  2. 将第一个元素存储在变量中
  3. 从优先级队列中将其删除
  4. 检查此已删除的第一个元素与新的peek元素之间的区别
  5. 如果差等于1,则将计数加1,然后重复步骤2和步骤3
  6. 如果差异大于1,则将计数器设置为1,然后重复步骤2和步骤3
  7. 如果差等于0,请重复步骤2和3
  8. 如果计数器大于先前的最大值,则将计数器存储为最大值
  9. 继续执行步骤4到7,直到到达优先队列为止
  10. 返回最大值

C++

// CPP program for the above approach
#include 
using namespace std;
 
int findLongestConseqSubseq(int arr[], int N)
{
    priority_queue, greater > pq;
    for (int i = 0; i < N; i++) {
       
        // adding element from
        // array to PriorityQueue
        pq.push(arr[i]);
    }
 
    // Storing the first element
    // of the Priority Queue
    // This first element is also
    // the smallest element
    int prev = pq.top();
    pq.pop();
 
    // Taking a counter variable with value 1
    int c = 1;
 
    // Storing value of max as 1
    // as there will always be
    // one element
    int max = 1;
    for (int i = 1; i < N; i++) {
       
        // check if current peek
        // element minus previous
        // element is greater then
        // 1 This is done because
        // if it's greater than 1
        // then the sequence
        // doesn't start or is broken here
        if (pq.top() - prev > 1) {
           
            // Store the value of counter to 1
            // As new sequence may begin
            c = 1;
 
            // Update the previous position with the
            // current peek And remove it
            prev = pq.top();
            pq.pop();
        }
 
        // Check if the previous
        //  element and peek are same
        else if (pq.top() - prev == 0) {
           
            // Update the previous position with the
            // current peek And remove it
            prev = pq.top();
            pq.pop();
        }
       
        // If the difference
        // between previous element and peek is 1
        else {
           
            // Update the counter
            // These are consecutive elements
            c++;
 
            // Update the previous position
            //  with the current peek And remove it
            prev = pq.top();
            pq.pop();
        }
       
        // Check if current longest
        // subsequence is the greatest
        if (max < c) {
           
            // Store the current subsequence count as
            // max
            max = c;
        }
    }
    return max;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
    int n = 7;
 
    cout << "Length of the Longest consecutive subsequence "
            "is "
         << findLongestConseqSubseq(arr, n);
    return 0;
}
// this code is contributed by Manu Pathria

Java

// Java Program to find longest consecutive
// subsequence This Program uses Priority Queue
import java.io.*;
import java.util.PriorityQueue;
public class Longset_Sub
{
    // return the length of the longest
    // subsequence of consecutive integers
    static int findLongestConseqSubseq(int arr[], int N)
    {
 
        PriorityQueue pq
            = new PriorityQueue();
        for (int i = 0; i < N; i++)
        {
            // adding element from
            // array to PriorityQueue
            pq.add(arr[i]);
        }
         
        // Storing the first element
        // of the Priority Queue
        // This first element is also
        // the smallest element
        int prev = pq.poll();
         
        // Taking a counter variable with value 1
        int c = 1;
         
        // Storing value of max as 1
        // as there will always be
        // one element
        int max = 1;
 
        for (int i = 1; i < N; i++)
        {
            // check if current peek
            // element minus previous
            // element is greater then
            // 1 This is done because
            // if it's greater than 1
            // then the sequence
            // doesn't start or is broken here
            if (pq.peek() - prev > 1)
            {
                // Store the value of counter to 1
                // As new sequence may begin
                c = 1;
                 
                // Update the previous position with the
                // current peek And remove it
                prev = pq.poll();
            }
             
            // Check if the previous
            //  element and peek are same
            else if (pq.peek() - prev == 0)
            {
                // Update the previous position with the
                // current peek And remove it
                prev = pq.poll();
            }
            // if the difference
            // between previous element and peek is 1
            else
            {
                // Update the counter
                // These are consecutive elements
                c++;
                  
                // Update the previous position
                //  with the current peek And remove it
                prev = pq.poll();
            }
 
            // Check if current longest
            // subsequence is the greatest
            if (max < c)
            {
                // Store the current subsequence count as
                // max
                max = c;
            }
        }
 
        return max;
    }
     
    // Driver Code
    public static void main(String args[])
        throws IOException
    {
        int arr[] = { 1, 9, 3, 10, 4, 20, 2 };
        int n = arr.length;
        System.out.println(
            "Length of the Longest consecutive subsequence is "
            + findLongestConseqSubseq(arr, n));
    }
}
// This code is contributed by Sudipa Sarkar
输出
Length of the Longest consecutive subsequence is 4