对于 [1, N] 中的每个值,找到该大小的所有子数组中存在的最小元素
给定一个大小为N的数组A[] ,任务是找到从1 到 N的所有大小的所有子数组中存在的最小元素,其中数组中的所有元素都在1 到 N的范围内
例子:
Input: A[ ] = {1, 2, 3}
Output: [-1, 2, 1]
Explanation: All subarrays of size 1 {{1}, {2}, {3}} there is no common value
For subarrays of size 2 {{1, 2}, {2, 3}} the minimum common element is 2
For subarrays of size 3 {{1, 2, 3}} the minimum common element is 1 Hence, ans=[-1, 2, 1]
Input: A[ ] = {1, 2, 1, 3, 1}
Output: [-1, 1, 1, 1, 1]
朴素方法:解决问题的基本思想是找到[1, N]范围内所有大小的所有子数组。现在对于相同大小的所有子数组,找到这些子数组中的最小公共元素。请按照以下步骤解决问题:
- 从i = 1 到 N迭代一个循环:
- 创建每个可能的大小为i的子数组。
- 计算所有子数组中每个元素的频率。
- 检查任何元素的出现是否等于该大小的子数组的总数
- 存储满足上述条件的第一个元素
- 返回最小公共元素的结果数组。
下面是上述方法的实现。
C++
// C++ code for the above approach
#include
using namespace std;
// Function to calculate
// the minimum element array
// from size 1 to N
vector Calculate_Min_array(vector& A,
int N)
{
// Minimum elemnt array(ans)
// Count array for every subsegment(cnt)
// Total occurence array in all
// subsegment of a given size(res)
vector ans(N + 1, -1), cnt(N + 1, 0),
res(N + 1, 0);
for (int i = 1; i <= N; i++) {
// Counting all the elements
// for every subsegment of size i
for (int j = 0; j < N - i + 1;
j++) {
for (int k = j; k < j + i;
k++) {
cnt[A[k]]++;
}
// If count of element is
// greater than 0 then
// increment its occurence
for (int k = 1; k <= N; k++) {
if (cnt[k]) {
// If element is present
// increase its count
res[k]++;
cnt[k] = 0;
}
}
}
// When occurence of an element
// is equal to total subsegment
// of size i then we will get the
// desired val for that subsegment
for (int j = 1; j <= N; j++) {
if (res[j] == (N - i + 1)) {
ans[i] = j;
break;
}
res[j] = 0;
}
}
// Final array
return ans;
}
// Print Function
void print(vector vec, int N)
{
vector ans
= Calculate_Min_array(vec, N);
// Output
for (int i = 1; i <= N; i++)
cout << ans[i] << " ";
cout << "\n";
}
// Driver code
int main()
{
// Intialization of array
vector A = { 1, 2, 3 };
int N = 3;
// Calling function
print(A, N);
return 0;
}
Java
// Java code for the above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to calculate
// the minimum element array
// from size 1 to N
public static int[] Calculate_Min_array(int A[], int N)
{
// Minimum elemnt array(ans)
// Count array for every subsegment(cnt)
// Total occurence array in all
// subsegment of a given size(res)
int ans[] = new int[N + 1];
int cnt[] = new int[N + 1];
int res[] = new int[N + 1];
for (int i = 0; i < N + 1; i++) {
ans[i] = -1;
}
for (int i = 1; i <= N; i++) {
// Counting all the elements
// for every subsegment of size i
for (int j = 0; j < N - i + 1; j++) {
for (int k = j; k < j + i; k++) {
cnt[A[k]]++;
}
// If count of element is
// greater than 0 then
// increment its occurence
for (int k = 1; k <= N; k++) {
if (cnt[k] != 0) {
// If element is present
// increase its count
res[k]++;
cnt[k] = 0;
}
}
}
// When occurence of an element
// is equal to total subsegment
// of size i then we will get the
// desired val for that subsegment
for (int j = 1; j <= N; j++) {
if (res[j] == (N - i + 1)) {
ans[i] = j;
break;
}
res[j] = 0;
}
}
// Final array
return ans;
}
// Print Function
public static void print(int vec[], int N)
{
int ans[] = Calculate_Min_array(vec, N);
// Output
for (int i = 1; i <= N; i++)
System.out.print(ans[i] + " ");
System.out.println();
}
public static void main(String[] args)
{
int A[] = { 1, 2, 3 };
int N = 3;
// Calling function
print(A, N);
}
}
// This code is contributed by Rohit Pradhan
Javascript
C++
// C++ code for the above approach:
#include
using namespace std;
// Function to calculate
// the minimum element array
// from size 1 to N
vector Calculate_Min_array(vector& A,
int N)
{
vector mx(N + 1, -1), ans(N + 1, -1);
vector pos[N + 1];
// Inserting the first position
// of elements
for (int i = 1; i <= N; i++) {
pos[i].push_back(0);
}
// Inserting the diff position
// of elements
for (int i = 0; i < N; i++) {
int x = A[i];
pos[x].push_back(i + 1);
}
// Inserting the last position
// of elements
for (int i = 1; i <= N; i++) {
pos[i].push_back(N + 1);
}
// Calculating max adjacent diff
// of elements
for (int i = 1; i <= N; i++) {
for (int j = 0;
j < pos[i].size() - 1; j++) {
mx[i] = max(mx[i],
pos[i][j + 1]
- pos[i][j]);
}
}
// Calculating ans for every subarray size
for (int i = 1; i <= N; i++) {
for (int j = mx[i]; j <= N; j++) {
// If ans[j] is already present
// move to next element
if (ans[j] != -1)
break;
// Otherwise store the ans[j]=i
ans[j] = i;
}
}
// Final array
return ans;
}
// Print Function
void print(vector A, int N)
{
// Calculation Minmun element array
// For Every subsegment length from
// 1 to N
vector ans
= Calculate_Min_array(A, N);
// Output
for (int i = 1; i <= N; i++)
cout << ans[i] << " ";
cout << "\n";
}
// Driver code
int main()
{
int N = 3;
// Intialization of array
vector A = { 1, 2, 3 };
print(A, N);
return 0;
}
-1 2 1
时间复杂度: O(N 3 )
辅助空间: O(N)
高效方法:高效解决问题的思路如下:
If two consecutive occurrence of a value A[i] is maximum x, then it is part of all the subarrays of size x but not of all subarrays with size less than x.
按照下面的步骤来实现上面的想法:
- 为每个第 i 个元素创建一个数组(例如pos[i] )以存储数组中第 i 个元素的位置。
- 然后计算每个元素的最大相邻差值。
- 从i = 1 迭代到 N :
- 从j = 最大相邻差 2 i到N开始另一个循环:
- 如果未找到第 j 个大小的子数组的答案,则i是所有j个大小的子数组的最小公共元素,并继续获取更高的j值。
- 否则,从循环中中断,因为所有更高的值也必须被填充
- 从j = 最大相邻差 2 i到N开始另一个循环:
- 返回结果数组。
下面是上述方法的实现:
C++
// C++ code for the above approach:
#include
using namespace std;
// Function to calculate
// the minimum element array
// from size 1 to N
vector Calculate_Min_array(vector& A,
int N)
{
vector mx(N + 1, -1), ans(N + 1, -1);
vector pos[N + 1];
// Inserting the first position
// of elements
for (int i = 1; i <= N; i++) {
pos[i].push_back(0);
}
// Inserting the diff position
// of elements
for (int i = 0; i < N; i++) {
int x = A[i];
pos[x].push_back(i + 1);
}
// Inserting the last position
// of elements
for (int i = 1; i <= N; i++) {
pos[i].push_back(N + 1);
}
// Calculating max adjacent diff
// of elements
for (int i = 1; i <= N; i++) {
for (int j = 0;
j < pos[i].size() - 1; j++) {
mx[i] = max(mx[i],
pos[i][j + 1]
- pos[i][j]);
}
}
// Calculating ans for every subarray size
for (int i = 1; i <= N; i++) {
for (int j = mx[i]; j <= N; j++) {
// If ans[j] is already present
// move to next element
if (ans[j] != -1)
break;
// Otherwise store the ans[j]=i
ans[j] = i;
}
}
// Final array
return ans;
}
// Print Function
void print(vector A, int N)
{
// Calculation Minmun element array
// For Every subsegment length from
// 1 to N
vector ans
= Calculate_Min_array(A, N);
// Output
for (int i = 1; i <= N; i++)
cout << ans[i] << " ";
cout << "\n";
}
// Driver code
int main()
{
int N = 3;
// Intialization of array
vector A = { 1, 2, 3 };
print(A, N);
return 0;
}
-1 2 1
时间复杂度:O(N) 因为虽然使用了嵌套循环,但最多填充了 N 个点,并且一个点最多被访问两次
辅助空间:O(N) 虽然使用了向量数组,但存储的总点数为 N