📌  相关文章
📜  在旋转数组中查找给定长度的最大和连续子数组的查询

📅  最后修改于: 2021-04-27 05:15:52             🧑  作者: Mango

给定N个整数的数组arr []和以下两种类型的{X,Y}形式的Q个查询:

  • 如果X = 1 ,则将给定数组向左旋转Y个位置。
  • 如果X = 2 ,则在数组的当前状态下打印长度为Y的最大和子数组。

例子:

天真的方法:最简单的方法是通过将元素逐一移位直到距离Y来旋转数组,以查询类型为1的查询,并生成所有长度为Y的子数组的和,如果查询的类型为2 ,则打印最大和。

时间复杂度: O(Q * N * Y)
辅助空间: O(N)

高效方法:为了优化上述方法,其思想是使用杂耍算法进行数组旋转,并使用滑动窗口技术找到长度为Y的最大和子数组。请按照以下步骤解决问题:

  1. 如果X = 1 ,则使用杂耍算法将数组旋转Y。
  2. 否则,如果X = 2 ,则使用滑动窗口技术找到长度Y的最大和子数组。
  3. 如果查询X1,则打印数组。
  4. 否则,打印大小为Y的最大和子数组。

下面是上述方法的实现:

C++
// C++ program for the above approach
  
#include 
using namespace std;
  
// Function to calculate the maximum
// sum of length k
int MaxSum(vector arr, int n,
           int k)
{
    int i, max_sum = 0, sum = 0;
  
    // Calculating the max sum for
    // the first k elements
    for (i = 0; i < k; i++) {
        sum += arr[i];
    }
    max_sum = sum;
  
    // Find subarray with maximum sum
    while (i < n) {
  
        // Update the sum
        sum = sum - arr[i - k] + arr[i];
        if (max_sum < sum) {
            max_sum = sum;
        }
        i++;
    }
  
    // Return maximum sum
    return max_sum;
}
  
// Function to calculate gcd of the
// two numbers n1 and n2
int gcd(int n1, int n2)
{
    // Base Case
    if (n2 == 0) {
        return n1;
    }
  
    // Recursively find the GCD
    else {
        return gcd(n2, n1 % n2);
    }
}
  
// Function to rotate the array by Y
vector RotateArr(vector arr,
                      int n, int d)
{
    // For handling k >= N
    int i = 0, j = 0;
    d = d % n;
  
    // Dividing the array into
    // number of sets
    int no_of_sets = gcd(d, n);
  
    for (i = 0; i < no_of_sets; i++) {
  
        int temp = arr[i];
        j = i;
  
        // Rotate the array by Y
        while (true) {
  
            int k = j + d;
  
            if (k >= n)
                k = k - n;
  
            if (k == i)
                break;
  
            arr[j] = arr[k];
            j = k;
        }
  
        // Update arr[j]
        arr[j] = temp;
    }
  
    // Return the rotated array
    return arr;
}
  
// Function that performs the queries
// on the given array
void performQuery(vector& arr,
                  int Q[][2], int q)
{
  
    int N = (int)arr.size();
  
    // Traverse each query
    for (int i = 0; i < q; i++) {
  
        // If query of type X = 1
        if (Q[i][0] == 1) {
  
            arr = RotateArr(arr, N,
                            Q[i][1]);
  
            // Print the array
            for (auto t : arr) {
                cout << t << " ";
            }
            cout << "\n";
        }
  
        // If query of type X = 2
        else {
            cout << MaxSum(arr, N, Q[i][1])
                 << "\n";
        }
    }
}
  
// Driver Code
int main()
{
    // Given array arr[]
    vector arr = { 1, 2, 3, 4, 5 };
  
    int q = 5;
  
    // Given Queries
    int Q[][2] = { { 1, 2 }, { 2, 3 }, 
                   { 1, 3 }, { 1, 1 }, 
                   { 2, 4 }
    };
  
    // Function Call
    performQuery(arr, Q, q);
  
    return 0;
}


Java
// Java program for 
// the above approach
class GFG{
  
// Function to calculate the maximum
// sum of length k
static int MaxSum(int []arr, 
                  int n, int k)
{
  int i, max_sum = 0, sum = 0;
  
  // Calculating the max sum for
  // the first k elements
  for (i = 0; i < k; i++) 
  {
    sum += arr[i];
  }
  max_sum = sum;
  
  // Find subarray with maximum sum
  while (i < n) 
  {
    // Update the sum
    sum = sum - arr[i - k] +
                arr[i];
    if (max_sum < sum) 
    {
      max_sum = sum;
    }
    i++;
  }
  
  // Return maximum sum
  return max_sum;
}
  
// Function to calculate gcd 
//  of the two numbers n1 and n2
static int gcd(int n1, int n2)
{
  // Base Case
  if (n2 == 0) 
  {
    return n1;
  }
  
  // Recursively find the GCD
  else 
  {
    return gcd(n2, n1 % n2);
  }
}
  
// Function to rotate the array by Y
static int []RotateArr(int []arr,
                       int n, int d)
{
  // For handling k >= N
  int i = 0, j = 0;
  d = d % n;
  
  // Dividing the array into
  // number of sets
  int no_of_sets = gcd(d, n);
  
  for (i = 0; i < no_of_sets; i++) 
  {
    int temp = arr[i];
    j = i;
  
    // Rotate the array by Y
    while (true) 
    {
      int k = j + d;
  
      if (k >= n)
        k = k - n;
  
      if (k == i)
        break;
  
      arr[j] = arr[k];
      j = k;
    }
  
    // Update arr[j]
    arr[j] = temp;
  }
  
  // Return the rotated array
  return arr;
}
  
// Function that performs the queries
// on the given array
static void performQuery(int []arr,
                         int Q[][], int q)
{
  int N = arr.length;
  
  // Traverse each query
  for (int i = 0; i < q; i++) 
  {
    // If query of type X = 1
    if (Q[i][0] == 1) 
    {
      arr = RotateArr(arr, N,
                      Q[i][1]);
  
      // Print the array
      for (int t : arr) 
      {
        System.out.print(t + " ");
      }
      System.out.print("\n");
    }
  
    // If query of type X = 2
    else 
    {
      System.out.print(MaxSum(arr, N, 
                              Q[i][1]) + "\n");
    }
  }
}
  
// Driver Code
public static void main(String[] args)
{
  // Given array arr[]
  int []arr = {1, 2, 3, 4, 5};
  
  int q = 5;
  
  // Given Queries
  int Q[][] = {{1, 2}, {2, 3}, 
               {1, 3}, {1, 1}, 
               {2, 4}};
  
  // Function Call
  performQuery(arr, Q, q);
}
}
  
// This code is contributed by Rajput-Ji


Python3
# Python3 program for the above approach
  
# Function to calculate the maximum
# sum of length k
def MaxSum(arr, n, k):
      
    i, max_sum = 0, 0
    sum = 0
  
    # Calculating the max sum for
    # the first k elements
    while i < k:
        sum += arr[i]
        i += 1
          
    max_sum = sum
  
    # Find subarray with maximum sum
    while (i < n):
  
        # Update the sum
        sum = sum - arr[i - k] + arr[i]
          
        if (max_sum < sum):
            max_sum = sum
              
        i += 1
  
    # Return maximum sum
    return max_sum
  
# Function to calculate gcd of the
# two numbers n1 and n2
def gcd(n1, n2):
      
    # Base Case
    if (n2 == 0):
        return n1
  
    # Recursively find the GCD
    else:
        return gcd(n2, n1 % n2)
  
# Function to rotate the array by Y
def RotateArr(arr, n, d):
      
    # For handling k >= N
    i = 0
    j = 0
    d = d % n
  
    # Dividing the array into
    # number of sets
    no_of_sets = gcd(d, n)
  
    for i in range(no_of_sets):
        temp = arr[i]
        j = i
  
        # Rotate the array by Y
        while (True):
            k = j + d
  
            if (k >= n):
                k = k - n
            if (k == i):
                break
  
            arr[j] = arr[k]
            j = k
  
        # Update arr[j]
        arr[j] = temp
  
    # Return the rotated array
    return arr
  
# Function that performs the queries
# on the given array
def performQuery(arr, Q, q):
  
    N = len(arr)
  
    # Traverse each query
    for i in range(q):
  
        # If query of type X = 1
        if (Q[i][0] == 1):
            arr = RotateArr(arr, N, Q[i][1])
  
            # Print the array
            for t in arr:
                print(t, end = " ")
                  
            print()
  
        # If query of type X = 2
        else:
            print(MaxSum(arr, N, Q[i][1]))
  
# Driver Code
if __name__ == '__main__':
      
    # Given array arr[]
    arr = [ 1, 2, 3, 4, 5 ]
  
    q = 5
  
    # Given Queries
    Q = [ [ 1, 2 ], [ 2, 3 ],
          [ 1, 3 ], [ 1, 1 ],
          [ 2, 4 ] ]
  
    # Function call
    performQuery(arr, Q, q)
  
# This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
class GFG{
      
// Function to calculate the maximum
// sum of length k
static int MaxSum(int[] arr, int n, 
                             int k)
{
    int i, max_sum = 0, sum = 0;
      
    // Calculating the max sum for
    // the first k elements
    for(i = 0; i < k; i++) 
    {
        sum += arr[i];
    }
    max_sum = sum;
      
    // Find subarray with maximum sum
    while (i < n) 
    {
          
        // Update the sum
        sum = sum - arr[i - k] +
                    arr[i];
                      
        if (max_sum < sum) 
        {
            max_sum = sum;
        }
        i++;
    }
      
    // Return maximum sum
    return max_sum;
}
   
// Function to calculate gcd 
//  of the two numbers n1 and n2
static int gcd(int n1, int n2)
{
      
    // Base Case
    if (n2 == 0) 
    {
        return n1;
    }
      
    // Recursively find the GCD
    else
    {
        return gcd(n2, n1 % n2);
    }
}
   
// Function to rotate the array by Y
static int []RotateArr(int []arr, int n,
                                  int d)
{
      
    // For handling k >= N
    int i = 0, j = 0;
    d = d % n;
      
    // Dividing the array into
    // number of sets
    int no_of_sets = gcd(d, n);
      
    for(i = 0; i < no_of_sets; i++) 
    {
        int temp = arr[i];
        j = i;
          
        // Rotate the array by Y
        while (true) 
        {
            int k = j + d;
              
            if (k >= n)
                k = k - n;
              
            if (k == i)
                break;
              
            arr[j] = arr[k];
            j = k;
        }
          
        // Update arr[j]
        arr[j] = temp;
    }
      
    // Return the rotated array
    return arr;
}
  
// Function that performs the queries
// on the given array
static void performQuery(int[] arr,
                         int[,] Q, int q)
{
    int N = arr.Length;
      
    // Traverse each query
    for(int i = 0; i < q; i++) 
    {
          
        // If query of type X = 1
        if (Q[i, 0] == 1) 
        {
            arr = RotateArr(arr, N,
                            Q[i, 1]);
          
            // Print the array
            for(int t = 0; t < arr.Length; t++) 
            {
                Console.Write(arr[t] + " ");
            }
            Console.WriteLine();
        }
      
        // If query of type X = 2
        else
        {
            Console.WriteLine(MaxSum(arr, N,
                                     Q[i, 1]));
        }
    }
}
  
// Driver code
static void Main()
{
      
    // Given array arr[]
    int[] arr = { 1, 2, 3, 4, 5 };
      
    int q = 5;
      
    // Given Queries
    int[,] Q = { { 1, 2 }, { 2, 3 }, 
                 { 1, 3 }, { 1, 1 }, 
                 { 2, 4 } };
      
    // Function call
    performQuery(arr, Q, q);
}
}
  
// This code is contributed by divyeshrabadiya07


输出:
3 4 5 1 2 
12
1 2 3 4 5 
2 3 4 5 1 
14

时间复杂度: O(Q * N),其中Q是查询数N是给定数组的大小。
辅助空间: O(N)