题解 | #MP3光标位置#
MP3光标位置
https://www.nowcoder.com/practice/eaf5b886bd6645dd9cfb5406f3753e15
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNext()) { // 注意 while 处理多个 case
int n = in.nextInt();
String cmd = in.next();
parseCmd(cmd, n);
}
}
public static void parseCmd(String commands, int n) {
int start = 1;
int end = Math.min(n, 4);
// 光标位置
int index = 1;
for (int i = 0; i < commands.length(); i++) {
// 根据向上移动和向下移动的公式,光标位置的变化
if (commands.charAt(i) == 'U') {
index = (index - 1 - 1 + n) % n + 1;
} else if (commands.charAt(i) == 'D') {
index = index % n + 1;
}
// 判断滑动窗口的位置是否需要改变
if (index < start) {
// 光标在窗口之上
start = index;
end = start + 3;
} else if (index > end) {
// 光标在窗口之下
end = index;
start = end - 3;
}
}
// 输出窗口内容
for (int i = start; i <= end; i++) {
System.out.print(i + " ");
}
System.out.println();
// 打印当前光标
System.out.println(index);
}
}
代码是赋值,说一下那个公式吧:
这行代码是在处理一个特定的滑动窗口问题,其中光标可以在一个序列上向上移动。这个问题中的滑动窗口有固定的长度,这里是4。光标的位置用 cursor 变量表示,它代表窗口的当前起始位置。
让我们分解这行代码:
cursor = (cursor - 1 - 1 + windowSize) % windowSize + 1;
- cursor - 1:这部分代码将光标向前移动一个位置。假设 cursor 的初始值是1,表示窗口的起始位置在序列的第一个元素上。那么 cursor - 1 将会把光标移动到序列的开始位置之前。
- - 1:由于我们已经将光标移动到了开始位置之前,再减1将会把光标移动到一个无效的位置(即序列的开始之前)。这个操作是为了模拟向上移动一个位置的效果。
- + windowSize:由于我们有一个固定大小的窗口,这个操作是将窗口的长度加到光标的当前位置。这样做的目的是为了在取模运算后,光标能够回到窗口的有效位置范围内。
- % windowSize:取模运算是用来确保光标的位置不会超出窗口的长度。如果光标移动后的位置加上窗口长度超出了窗口的最后一个位置,取模运算将会把光标位置调整到窗口内的一个有效位置。
- + 1:最后,我们再加上1,这是因为我们希望光标始终位于窗口的第一个位置,而不是在窗口开始之前的位置。这样,光标就正确地向上移动了一个位置,并且仍然保持在窗口的起始位置。
举个例子,如果 windowSize 是4,cursor 的初始值是1,那么执行这行代码的过程如下:
cursor - 1将光标移动到位置0(序列开始之前)。- 再减1,光标移动到位置-1(一个无效的位置)。
+ windowSize将光标移动到位置3(因为4 - 1 + 4 = 7,超出了窗口长度,但光标仍然在窗口内)。% windowSize确保光标位置在0到3之间,这里是3 % 4 = 3(已经是有效位置,无需改变)。+ 1将光标移动到位置4,这是窗口的下一个有效起始位置。
这样,光标就成功地向上移动了一个位置,同时保持在滑动窗口的范围内。


