题目链接
题目描述
小红拿到了一个大小为 的环形数组,她有
次询问。
每次查询会给定一个初始位置 pos
(1-indexed),一个方向 dir
('L' 或 'R'),以及一个步数 k
。
你需要计算从 pos
开始,按 dir
方向走 k
步后,最终落在哪个元素上。
解题思路
这是一个典型的环形数组问题,核心是利用模运算(Modulo Arithmetic)来处理“环绕”的边界情况。
1. 索引转换
题目中给定的位置是从 1 开始的(1-based),而编程中数组的索引通常是从 0 开始的(0-based)。因此,在进行计算前,我们需要将输入的 1-based 位置 pos
转换为 0-based 索引 start_idx
:
2. 向右移动 ('R')
从 0-based 索引 start_idx
向右移动 步,新的索引是
start_idx + k
。为了模拟环形,我们将结果对数组大小 取模。
3. 向左移动 ('L')
从 0-based 索引 start_idx
向左移动 步,新的索引是
start_idx - k
。同样需要对 取模。
这里需要注意一个细节:在 C++ 和 Java 等语言中,对负数取模的结果可能是负数(例如 -1 % 5
的结果是 -1
),这会导致数组越界。
为了保证结果始终是 [0, n-1]
范围内的非负整数,我们使用一个通用的技巧:先取模,再加上 ,再取模。
这个公式可以确保无论 start_idx - k
是正还是负,最终结果都是一个有效的 0-based 索引。
(在 Python 中,%
运算符的定义方式使得 (start_idx - k) % n
就能直接得到正确的结果,但使用上述通用公式也是完全正确的。)
4. 获取结果
计算出最终的 0-based 索引 final_idx
后,从数组中取出 a[final_idx]
的值即可。
代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, q;
cin >> n >> q;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
for (int i = 0; i < q; ++i) {
int pos, k;
char dir;
cin >> pos >> dir >> k;
// Convert to 0-based index
int start_idx = pos - 1;
int final_idx;
if (dir == 'R') {
final_idx = (start_idx + k) % n;
} else { // dir == 'L'
final_idx = ((start_idx - k) % n + n) % n;
}
cout << a[final_idx] << endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int q = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
for (int i = 0; i < q; i++) {
int pos = sc.nextInt();
String dir = sc.next();
int k = sc.nextInt();
// Convert to 0-based index
int startIdx = pos - 1;
int finalIdx;
if (dir.equals("R")) {
finalIdx = (startIdx + k) % n;
} else { // dir.equals("L")
finalIdx = ((startIdx - k) % n + n) % n;
}
System.out.println(a[finalIdx]);
}
}
}
import sys
def solve():
try:
n, q = map(int, sys.stdin.readline().split())
a = list(map(int, sys.stdin.readline().split()))
for _ in range(q):
pos, dir, k_str = sys.stdin.readline().split()
pos = int(pos)
k = int(k_str)
# Convert to 0-based index
start_idx = pos - 1
final_idx = 0
if dir == 'R':
final_idx = (start_idx + k) % n
else: # dir == 'L'
# In Python, '%' with negative numbers works as expected mathematically
# e.g., -1 % 5 is 4. So the +n trick is not strictly necessary.
final_idx = (start_idx - k) % n
print(a[final_idx])
except (IOError, ValueError):
return
solve()
算法及复杂度
-
算法:模拟 / 模运算
-
时间复杂度:
。
- 读取
个数组元素需要
的时间。
- 处理
次查询,每次查询都是
的数学运算。
- 读取
-
空间复杂度:
。
- 需要
的空间来存储数组元素。
- 需要