📌  相关文章
📜  查询数组左右循环移位

📅  最后修改于: 2022-05-13 01:57:48.242000             🧑  作者: Mango

查询数组左右循环移位

给定一个包含N个整数的数组A。共有三种类型的命令:

  • 1 x :向右循环移动数组 x 次。如果一个数组是 a[0], a[1], ...., a[n – 1],那么经过一次右循环移位后,数组将变为 a[n – 1], a[0], a[1] , ...., a[n – 2]。
  • 2 y :左循环将数组移动 y 次。如果一个数组是 a[0], a[1], ...., a[n – 1],那么经过一次左循环后,该数组将变为 a[1], ...., a[n – 2], a [n - 1],一个[0]。
  • 3 lr:打印子数组a[l…r](包括l和r)中所有整数的总和。

给定Q个查询,任务是执行每个查询。

例子:

Input : n = 5, arr[] = { 1, 2, 3, 4, 5 }
        query 1 = { 1, 3 }
        query 2 = { 3, 0, 2 }
        query 3 = { 2, 1 }
        query 4 = { 3, 1, 4 }
Output : 12
         11
Initial array arr[] = { 1, 2, 3, 4, 5 }
After query 1, arr[] = { 3, 4, 5, 1, 2 }.
After query 2, sum from index 0 to index 
               2 is 12, so output 12.
After query 3, arr[] = { 4, 5, 1, 2, 3 }.
After query 4, sum from index 1 to index 
               4 is 11, so output 11.

方法1:(蛮力)实现三个函数,rotateR(arr,k)将数组arr右旋转k次,rotateL(arr,k)将数组arr左旋转k次,sum(arr,l,r ) 这将输出从索引 l 到索引 r 的数组 arr 的总和。在值 1、2、3 的输入上调用相应的函数。

方法 2:(有效方法)最初,没有旋转,我们有许多查询要求范围 od 索引中存在的整数总和。
我们可以计算数组中所有元素的前缀和, prefixsum[i]将表示直到第 i 个索引的所有整数的总和。
现在,如果我们想找到两个索引(即 l 和 r)之间的元素之和,我们只需计算 prefixsum[r] – prefixsum[l – 1] 就可以在常数时间内计算它。
现在对于旋转,如果我们为每个查询旋转数组,那将是非常低效的。
我们只需要跟踪净旋转。如果跟踪数为负数,则表示左旋占优,否则右旋占优。当我们跟踪净旋转时,我们需要做mod n 。每旋转 n 次后,数组将返回其原始状态。
我们需要以这样一种方式观察它,即每次旋转数组时,只有它的索引在变化。
如果我们需要回答任何第三种类型的查询,我们有 l 和 r。我们需要找出原始顺序中的 l 和 r 是什么。我们可以通过将净旋转添加到索引并取 mod n 来轻松找到它。
每个命令都可以在 O(1) 时间内执行。

下面是这种方法的 C++ 实现:

C++
// C++ Program to solve queries on Left and Right
// Circular shift on array
#include 
using namespace std;
 
// Function to solve query of type 1 x.
void querytype1(int* toRotate, int times, int n)
{
    // Decreasing the absolute rotation
    (*toRotate) = ((*toRotate) - times) % n;
}
 
// Function to solve query of type 2 y.
void querytype2(int* toRotate, int times, int n)
{
    // Increasing the absolute rotation.
    (*toRotate) = ((*toRotate) + times) % n;
}
 
// Function to solve queries of type 3 l r.
void querytype3(int toRotate, int l, int r,
                      int preSum[], int n)
{
    // Finding absolute l and r.
    l = (l + toRotate + n) % n;
    r = (r + toRotate + n) % n;
 
    // if l is before r.
    if (l <= r)
        cout << (preSum[r + 1] - preSum[l]) << endl;   
 
    // If r is before l.
    else
        cout << (preSum[n] + preSum[r + 1] - preSum[l])
             << endl;   
}
 
// Wrapper Function solve all queries.
void wrapper(int a[], int n)
{
    int preSum[n + 1];
    preSum[0] = 0;
 
    // Finding Prefix sum
    for (int i = 1; i <= n; i++)
        preSum[i] = preSum[i - 1] + a[i - 1];
 
    int toRotate = 0;
 
    // Solving each query
    querytype1(&toRotate, 3, n);
    querytype3(toRotate, 0, 2, preSum, n);
    querytype2(&toRotate, 1, n);
    querytype3(toRotate, 1, 4, preSum, n);
}
 
// Driver Program
int main()
{
    int a[] = { 1, 2, 3, 4, 5 };
    int n = sizeof(a) / sizeof(a[0]);
    wrapper(a, n);
    return 0;
}


Python3
# Python Program to solve queries on Left and Right
# Circular shift on array
 
# Function to solve query of type 1 x.
def querytype1(toRotate, times, n):
   
    # Decreasing the absolute rotation
    toRotate = (toRotate - times) % n
    return toRotate
 
# Function to solve query of type 2 y.
def querytype2(toRotate, times, n):
   
    # Increasing the absolute rotation.
    toRotate = (toRotate + times) % n
    return toRotate
 
# Function to solve queries of type 3 l r.
def querytype3( toRotate, l, r, preSum, n):
   
    # Finding absolute l and r.
    l = (l + toRotate + n) % n
    r = (r + toRotate + n) % n
 
    # if l is before r.
    if (l <= r):
        print((preSum[r + 1] - preSum[l]))  
 
    # If r is before l.
    else:
        print((preSum[n] + preSum[r + 1] - preSum[l]))
 
# Wrapper Function solve all queries.
def wrapper( a, n):
    preSum = [ 0 for i in range(n + 1)]
     
    # Finding Prefix sum
    for i in range(1,n+1):
        preSum[i] = preSum[i - 1] + a[i - 1]
 
    toRotate = 0
 
    # Solving each query
    toRotate = querytype1(toRotate, 3, n)
    querytype3(toRotate, 0, 2, preSum, n)
    toRotate = querytype2(toRotate, 1, n)
    querytype3(toRotate, 1, 4, preSum, n);
 
# Driver Program
a = [ 1, 2, 3, 4, 5 ]
n = len(a)
wrapper(a, n)
 
# This code is contributed by rohan07.


Javascript


输出:

12
11