给定一个从1到N的整数的排列和一个整数M ,任务是检查给定排列的任何子数组是否是从1到M的整数的排列。
例子:
Input: arr[] = {4, 5, 1, 3, 2, 6}, M = 3
Output: Yes
{4, 5, 1, 3, 2, 6} is the required subarray.
Input: arr[] = {4, 5, 1, 3, 2, 6}, M = 4
Output: No
天真的方法:天真的方法是生成所有M大小的子数组,并查看是否存在任何此类子数组。但是,如果给定的排列太大,则此方法将在O(N 3 )中运行,因此将很耗时。
高效的方法:更好的解决方案是使用Hashing 。
- 从主要排列来看,每个整数的位置都存储在地图/字典中。
- 现在,观察到如果存在一个从1到m的排列的子数组,则范围[1,m]中的所有数字将以排序或随机的方式在主排列中占据m个连续的位置。
- 它们的位置在排序时也应以m连续数字开头,从最小位置/值x及其m-1个连续位置开始。
- 因此,可以计算每个整数1到n的“位置总和” ,其中sum_of_position(k)= sumcur = Position_of_1 + Position_of_2 +…Position_of_k 。
- 令上述系列的最小元素为x 。当位置排序时,这将是第一个元素,其余元素将是连续的。
- 然后,如果存在所需的子数组,则sum_of_position(m)必须为x +(x + 1)+ ..(x + m-1){m个连续项} = x * m – m + m *(m + 1 )/ 2 。
- 如果整数1到m的所有位置的总和为该总和,则对于给定的m,返回true,否则不存在此类子数组。
下面是上述方法的实现。
CPP
// C++ implementation of the approach
#include
using namespace std;
typedef long long int ll;
// Function that returns true if the
// required subarray exists
// in the given array
bool subArray(ll* arr, ll n, ll m)
{
ll i;
// Map to store the positions of
// each integer in the original
// permutation
unordered_map mp;
for (i = 0; i < n; i++) {
// To store the address of each
// entry in arr[n] but with
// 1-based indexing
mp[arr[i]] = i + 1;
}
ll sumcur = 0;
// To track minimum position sumcur
// for sum of all positions
// till this position
ll p = INT_MAX;
vector ans;
for (i = 1; i <= m; i++) {
// Summing up addresses
sumcur += mp[i];
// Tracking minimum address
// encountered till now
p = min(p, mp[i]);
// The sum of the addresses if
// it forms the required subarray
ll val = p * i - i + (i * (i + 1)) / 2;
if (i == m) {
// If current sum of address
// is equal to val
if (val == sumcur) {
return true;
}
else
return false;
}
}
}
// Driver code
int main()
{
ll arr[] = { 4, 5, 1, 3, 2, 6 };
int n = sizeof(arr) / sizeof(int);
ll m = 3;
if (subArray(arr, n, m))
cout << "Yes";
else
cout << "No";
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG
{
// Function that returns true if the
// required subarray exists
// in the given array
static boolean subArray(int[] arr, int n, int m)
{
int i;
// Map to store the positions of
// each integer in the original
// permutation
HashMap mp =
new HashMap ();
for (i = 0; i < n; i++)
{
// To store the address of each
// entry in arr[n] but with
// 1-based indexing
mp.put(arr[i], i + 1);
}
int sumcur = 0;
// To track minimum position sumcur
// for sum of aint positions
// tiint this position
int p = Integer.MAX_VALUE;
Vector ans = new Vector();
for (i = 1; i <= m; i++)
{
// Summing up addresses
sumcur += mp.get(i);
// Tracking minimum address
// encountered tiint now
p = Math.min(p, mp.get(i));
// The sum of the addresses if
// it forms the required subarray
int val = p * i - i + (i * (i + 1)) / 2;
if (i == m)
{
// If current sum of address
// is equal to val
if (val == sumcur)
{
return true;
}
else
return false;
}
}
return false;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 4, 5, 1, 3, 2, 6 };
int n = arr.length;
int m = 3;
if (subArray(arr, n, m))
System.out.print("Yes");
else
System.out.print("No");
}
}
// This code is contributed by Rajput-Ji
Python3
# Python3 implementation of the approach
# Function that returns true if the
# required subarray exists
# in the given array
def subArray(arr, n, m):
i = 0
# Map to store the positions of
# each integer in the original
# permutation
mp = dict()
for i in range(n):
# To store the address of each
# entry in arr[n] but with
# 1-based indexing
mp[arr[i]] = i + 1
sumcur = 0
# To track minimum position sumcur
# for sum of a positions
# ti this position
p = 10**9
ans = []
for i in range(1, m + 1):
# Summing up addresses
sumcur += mp[i]
# Tracking minimum address
# encountered ti now
p = min(p, mp[i])
# The sum of the addresses if
# it forms the required subarray
val = p * i - i + (i * (i + 1)) / 2
if (i == m):
# If current sum of address
# is equal to val
if (val == sumcur):
return True
else:
return False
# Driver code
arr = [4, 5, 1, 3, 2, 6]
n = len(arr)
m = 3
if (subArray(arr, n, m)):
print("Yes")
else:
print("No")
# This code is contributed by mohit kumar 29
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG
{
// Function that returns true if the
// required subarray exists
// in the given array
static bool subArray(int[] arr, int n, int m)
{
int i;
// Map to store the positions of
// each integer in the original
// permutation
Dictionary mp =
new Dictionary ();
for (i = 0; i < n; i++)
{
// To store the address of each
// entry in arr[n] but with
// 1-based indexing
mp.Add(arr[i], i + 1);
}
int sumcur = 0;
// To track minimum position sumcur
// for sum of aint positions
// tiint this position
int p = int.MaxValue;
List ans = new List();
for (i = 1; i <= m; i++)
{
// Summing up addresses
sumcur += mp[i];
// Tracking minimum address
// encountered tiint now
p = Math.Min(p, mp[i]);
// The sum of the addresses if
// it forms the required subarray
int val = p * i - i + (i * (i + 1)) / 2;
if (i == m)
{
// If current sum of address
// is equal to val
if (val == sumcur)
{
return true;
}
else
return false;
}
}
return false;
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 4, 5, 1, 3, 2, 6 };
int n = arr.Length;
int m = 3;
if (subArray(arr, n, m))
Console.Write("Yes");
else
Console.Write("No");
}
}
// This code is contributed by 29AjayKumar
输出:
Yes
时间复杂度: O(N)