给定一个包含 N 个数字的数组,找到最长子数组的长度,使得 K 是插入时的第二大元素。
例子:
Input: a[] = {9, 5, 5, 6, 8}, K = 7
Output: 4
The longest subarray is {9, 5, 5, 6}, in which if K is inserted it becomes {9, 5, 5, 6, 7}, and
7 is the second largest element in the array
Input: a[] = {9, 5, 5, 6, 8}, K = 10
Output: 0
Since the maximum number in the array is less than that of K, hence it is not possible.
Input: a[] = {8, 5, 10, 10, 8}, K = 9
Output: 5
9 is the second largest element of whole array
一种天真的方法是迭代每个可能的子数组并检查插入 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)