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

📅  最后修改于: 2021-10-27 08:27:41             🧑  作者: Mango

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

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

  • 将前后两个指针初始化为 0,以及标记索引已访问或未访问的已访问数组
  • 我们需要一个集合容器,以便我们可以在 O(log N) 和 unordered_map 中计算任何范围前端中的第二大元素来计算数组中元素的频率,以决定从集合中删除。
  • 首先检查是否存在大于 K 的元素,如果不存在这样的元素,则子数组是不可能的。
  • 插入集合中a[end]处的元素,如果之前没有访问过索引端,则增加其在映射中的频率,以避免多次插入同一索引。
  • 如果集合只包含一个元素,那么插入 K 是可能的,因为我们只有元素,并且因为我们知道至少存在一个元素 > k ,那么这个子数组可以是最长子数组的一部分,因此我们计算它并向前移动结束指针。
  • 如果集合包含多个元素,则 s.end() 指针指向最后一个元素之后,因此将其减少两次将给我们在范围前端中的第二大元素。
  • 如果第二大元素大于K,那么这个子数组是不可能的,因此我们需要将第一个指针向前移动,但在此之前,请检查a[front]的频率是否为1 ,如果是,然后将其从集合中删除,否则只需将 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


Javascript


输出:
4

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