📌  相关文章
📜  最长的子数组,只有一个大于k的值

📅  最后修改于: 2021-06-26 02:19:00             🧑  作者: Mango

给定N个数字的数组,请找到最长子数组的长度,以使K是插入时第二大的元素。
例子:

天真的方法是对每个可能的子数组进行迭代,并检查在插入K时是否成为第二大元素。天真的,我们可以存储所有可能的最长子数组的长度。
时间复杂度: O(N ^ 2)
一个有效的解决方案是使用双指针技术来解决上述问题。以下是解决上述问题的算法。

  • 将两个指针front和end初始化为0,以及一个访问数组,该数组指示索引是否已访问。
  • 我们需要一个集合容器,以便我们可以在O(log N)中任何范围前端的第二大元素和一个unordered_map来计数数组中元素的频率,以决定从集合中删除。
  • 最初检查是否存在大于K的元素,如果不存在这样的元素,则子数组是不可能的。
  • 如果之前未访问过索引末端,则将元素插入集合中的a [end]并增加其在映射中的频率,以避免多次插入相同的索引。
  • 如果集合中仅包含一个元素,则因为我们只有元素,所以可以插入K,并且因为我们知道至少有一个元素> k ,所以此子数组可以是最长子数组的一部分,因此我们对其进行计数并向前移动结束指针。
  • 如果集合包含一个以上的元素,则s.end()指针指向最后一个元素,因此将其减少两次将使我们在范围前端的第二大元素。
  • 如果第二大元素大于K,则此子数组是不可能的,因此我们需要将第一个指针向前移动,但是在执行此操作之前,请检查a [front]的频率是否为1 ,如果为1 ,则为0。 ,然后将其从集合中删除,否则只需将map的频率降低1,因为该元素将存在于任何index> front中。将前指针增加一。
  • 如果第二大元素不大于K,则只需将结束指针增加1。
  • 存储最大长度的前端,然后将其返回。

下面是上述方法的实现:

C++
// C++ program to find the length of the longest
// subarray such that K is the second largest element
// on insertion
#include 
using namespace std;
 
// Function to find the length of longest subarray
int lengthOfLongestSubarray(int a[], int n, int k)
{
    bool flag = 0;
 
    // Check if any element exists which is
    // greater than k or not
    for (int i = 0; i < n; i++) {
        if (a[i] > k)
            flag = 1;
    }
 
    if (!flag) {
        return 0;
    }
 
    // two pointers used
    int front = 0;
    int end = 0;
 
    // find the maximum length
    int maxi = 0;
 
    // Map used to count frequencies
    unordered_map mpp;
 
    // set used to find the second largest
    // element in range front-end
    set s;
 
    // initialize all index of array as 0
    bool vis[n];
    memset(vis, 0, sizeof vis);
 
    // iterate till any of the pointer exceeds N
    while (front < n && end < n) {
 
        // length of longest subarray
        maxi = max(maxi, end - front);
 
        // if the current index has not been
        // visited previously then insert it
        // in the set and increase the frequency
        // and mark it as visited.
        if (!vis[end]) {
            mpp[a[end]]++;
            s.insert(a[end]);
            vis[end] = 1;
        }
 
        // find the largest element in the set
        auto it = s.end();
 
        // if only one element is there in set,
        // then insertion of K is possible which
        // will include other elements
        if (s.size() == 1) {
 
            // increase the second pointer in order
            // to include more elements in the subarray
            end++;
            continue;
        }
 
        // twice decrease the
        // iterator as s.end() points to
        // after the last element
        it--;
 
        // second largest element in set
        it--;
        int el = *it;
 
        // if the second largest element is greater than the
        // K, then it is not possible to insert element
        // in range front-end, and thus decrease the
        // frequency of a[front] and remove from set
        // accordingly
        if (el > k) {
            if (mpp[a[front]] == 1) {
                s.erase(a[front]);
                mpp[a[front]]--;
            }
            else
                mpp[a[front]]--;
 
            // move ahead the first pointer
            front++;
        }
        else {
 
            // increase the second pointer
            // if the second largest element is smaller
            // than or equals to K
            end++;
        }
    }
 
    // at then end also check for last subarray length
    maxi = max(maxi, end - front);
 
    return maxi;
}
 
// Driver Code
int main()
{
    int a[] = { 9, 5, 5, 6, 8 };
    int n = sizeof(a) / sizeof(a[0]);
    int k = 7;
 
    cout << lengthOfLongestSubarray(a, n, k);
 
    return 0;
}


Java
// Java program to find the length of the longest
// subarray such that K is the second largest element
// on insertion
import java.io.*;
import java.util.*;
class GFG
{
 
  // Function to find the length of longest subarray
  static int lengthOfLongestSubarray(int a[], int n, int k)
  {
    int flag = 0;
 
    // Check if any element exists which is
    // greater than k or not
    for (int i = 0; i < n; i++)
    {
      if (a[i] > k)
        flag = 1;
    }
    if (flag == 0)
    {
      return 0;
    }
 
    // two pointers used
    int front = 0;
    int end = 0;
 
    // find the maximum length
    int maxi = 0;    
    Map mpp = new HashMap();
    Set s = new HashSet();
 
    // initialize all index of array as 0
    int[] vis = new int[n];
 
    // iterate till any of the pointer exceeds N
    while (front < n && end < n)
    {
 
      // length of longest subarray
      maxi = Math.max(maxi, end - front);
 
      // if the current index has not been
      // visited previously then insert it
      // in the set and increase the frequency
      // and mark it as visited.        
      if (vis[end] == 0)
      {
        if(mpp.containsKey(a[end]))
        {
          mpp.put(a[end], mpp.get(a[end]) + 1);
        }
        else
        {
          mpp.put(a[end], 1);
        }
        s.add(a[end]);
        vis[end] = 1;
      }     
      int it = s.size();
      List S = new ArrayList(s);
      Collections.sort(S);
 
      // if only one element is there in set,
      // then insertion of K is possible which
      // will include other elements
      if (S.size() == 1)
      {
 
        // increase the second pointer in order
        // to include more elements in the subarray
        end++;
        continue;
      }
 
      // twice decrease the
      // iterator as s.end() points to
      // after the last element
      it--;
 
      // second largest element in set
      it--;
      int el = S.get(it);
 
      // if the second largest element is greater than the
      // K, then it is not possible to insert element
      // in range front-end, and thus decrease the
      // frequency of a[front] and remove from set
      // accordingly
 
      if (el > k)
      {
        if(mpp.get(a[front]) == 1)
        {
          mpp.put(a[front], mpp.get(a[front]) - 1);
        }
        else
        {
          mpp.put(a[front], mpp.get(a[front]) - 1);  
        }
 
        // move ahead the first pointer
        front++;
      }
      else
      {
 
        // increase the second pointer
        // if the second largest element is smaller
        // than or equals to K
        end++;
      }
    }
 
    // at then end also check for last subarray length
    maxi = Math.max(maxi, end - front);
    return maxi;
 
  }
 
  // Driver Code
  public static void main (String[] args)
  {
    int[] a = { 9, 5, 5, 6, 8 };
    int n = a.length;
    int k = 7;
    System.out.println(lengthOfLongestSubarray(a, n, k));
  }
}
 
// This code is contributed by avanitrachhadiya2155


Python3
# Python3 program to find the length of
# the longest subarray such that K is
# the second largest element on insertion
 
# Function to find the length of longest subarray
def lengthOfLongestSubarray(a, n, k):
    flag = 0
 
    # Check if any element exists which is
    # greater than k or not
    for i in range(n):
        if (a[i] > k):
            flag = 1
 
    if (flag == 0):
        return 0
 
    # two pointers used
    front = 0
    end = 0
 
    # find the maximum length
    maxi = 0
 
    # Map used to count frequencies
    mpp = dict()
 
    # set used to find the second largest
    # element in range front-end
    s = dict()
 
    # initialize all index of array as 0
    vis = [0] * n
 
    # iterate till any of the pointer exceeds N
    while (front < n and end < n):
 
        # length of longest subarray
        maxi = max(maxi, end - front)
 
        # if the current index has not been
        # visited previously then insert it
        # in the set and increase the frequency
        # and mark it as visited.
        if (vis[end] == 0):
            mpp[a[end]] = mpp.get(a[end], 0) + 1
            s[a[end]] = s.get(a[end], 0) + 1
            vis[end] = 1
 
        # find the largest element in the set
        iit = sorted(list(s))
        it = len(iit)
         
        # if only one element is there in set,
        # then insertion of K is possible which
        # will include other elements
        if (len(s) == 1):
 
            # increase the second pointer in order
            # to include more elements in the subarray
            end += 1
            continue
 
        # twice decrease the
        # iterator as s.end() points to
        # after the last element
        it -= 1
 
        # second largest element in set
        it -= 1
        el = iit[it]
 
        # if the second largest element is greater than the
        # K, then it is not possible to insert element
        # in range front-end, and thus decrease the
        # frequency of a[front] and remove from set
        # accordingly
        if (el > k):
            if (mpp[a[front]] == 1):
                del s[a[front]]
                mpp[a[front]] -= 1
            else:
                mpp[a[front]] -= 1
 
            # move ahead the first pointer
            front += 1
        else :
 
            # increase the second pointer
            # if the second largest element is
            # smaller than or equals to K
            end += 1
 
    # at then end also check for
    # last subarray length
    maxi = max(maxi, end - front)
 
    return maxi
 
# Driver Code
a  = [9, 5, 5, 6, 8]
n = len(a)
k = 7
 
print(lengthOfLongestSubarray(a, n, k))
 
# This code is contributed by Mohit Kumar


C#
// C# program to find the length of the longest
// subarray such that K is the second largest element
// on insertion
using System;
using System.Collections.Generic;
public class GFG
{
 
  // Function to find the length of longest subarray
  static int lengthOfLongestSubarray(int[] a, int n, int k)
  {
    int flag = 0;
 
    // Check if any element exists which is
    // greater than k or not
    for (int i = 0; i < n; i++)
    {
      if (a[i] > k)
        flag = 1;
    }
    if (flag == 0)
    {
      return 0;
    }
 
    // two pointers used
    int front = 0;
    int end = 0;
 
    // find the maximum length
    int maxi = 0;    
 
    Dictionary mpp =new Dictionary();
    SortedSet s = new SortedSet();
 
    // initialize all index of array as 0
    int[] vis = new int[n];
 
    // iterate till any of the pointer exceeds N
    while (front < n && end < n)
    {
 
      // length of longest subarray
      maxi = Math.Max(maxi, end - front);  
 
      // if the current index has not been
      // visited previously then insert it
      // in the set and increase the frequency
      // and mark it as visited.        
      if (vis[end] == 0)
      {
        if(mpp.ContainsKey(a[end]))
        {
          mpp[a[end]]++;
        }
        else
        {
          mpp.Add(a[end],1);
        }
        s.Add(a[end]);
        vis[end] = 1;
      }
      int it = s.Count;
      List S = new List(s);
      if(S.Count == 1)
      {
        // increase the second pointer in order
        // to include more elements in the subarray
        end++;
        continue;
      }
 
      // twice decrease the
      // iterator as s.end() points to
      // after the last element
      it--;
 
      // second largest element in set
      it--;
      int el = S[it];
 
      // if the second largest element is greater than the
      // K, then it is not possible to insert element
      // in range front-end, and thus decrease the
      // frequency of a[front] and remove from set
      // accordingly        
      if (el > k)
      {
        if(mpp[a[front]] == 1)
        {
          mpp[a[front]]--;
        }
        else
        {
          mpp[a[front]]--;
        }
        front++;
      }
      else
      {
        // increase the second pointer
        // if the second largest element is smaller
        // than or equals to K
        end++;
      }
    }
 
    // at then end also check for last subarray length
    maxi = Math.Max(maxi, end - front);
    return maxi;
  }
 
  // Driver code
  static public void Main (){
    int[] a = { 9, 5, 5, 6, 8 };
    int n = a.Length;
    int k = 7;
 
    Console.WriteLine(lengthOfLongestSubarray(a, n, k));
  }
}
 
// This code is contributed by rag2127


输出:
4

时间复杂度:O(N * log N)

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。