📌  相关文章
📜  满足给定条件的子数组排列

📅  最后修改于: 2021-04-27 21:45:18             🧑  作者: Mango

给定一个从1N的整数的排列和一个整数M ,任务是检查给定排列的任何子数组是否是从1M的整数的排列。

例子:

天真的方法:天真的方法是生成所有M大小的子数组,并查看是否存在任何此类子数组。但是,如果给定的排列太大,则此方法将在O(N 3 )中运行,因此将很耗时。

高效的方法:更好的解决方案是使用Hashing

  1. 从主要排列来看,每个整数的位置都存储在地图/字典中。
  2. 现在,观察到如果存在一个从1到m的排列的子数组,则范围[1,m]中的所有数字将以排序或随机的方式在主排列中占据m个连续的位置。
  3. 它们的位置在排序时也应以m连续数字开头,从最小位置/值x及其m-1个连续位置开始。
  4. 因此,可以计算每个整数1到n的“位置总和” ,其中sum_of_position(k)= sumcur = Position_of_1 + Position_of_2 +…Position_of_k
  5. 令上述系列的最小元素x 。当位置排序时,这将是第一个元素,其余元素将是连续的。
  6. 然后,如果存在所需的子数组,则sum_of_position(m)必须为x +(x + 1)+ ..(x + m-1){m个连续项} = x * m – m + m *(m + 1 )/ 2
  7. 如果整数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)