题目
解题思路
这是一个模拟题,需要处理以下几种情况:
-
歌曲总数 ≤ 4:不需要翻页,只移动光标
- Up键:光标在第一首时移到最后,否则向上移动
- Down键:光标在最后时移到第一首,否则向下移动
-
歌曲总数 > 4:需要处理翻页
- 特殊翻页:
- 第一页按Up:显示最后一页,光标到最后
- 最后一页按Down:显示第一页,光标到最前
- 一般翻页:
- 光标在当前页第一首按Up:向上翻页
- 光标在当前页最后一首按Down:向下翻页
- 特殊翻页:
代码
#include <iostream>
#include <vector>
using namespace std;
class MP3Player {
private:
int n; // 总歌曲数
int cursor; // 当前光标位置(1-based)
int pageStart; // 当前页面起始歌曲编号(1-based)
void handleSmallList(char cmd) {
if (cmd == 'U') {
cursor = (cursor == 1) ? n : cursor - 1;
} else {
cursor = (cursor == n) ? 1 : cursor + 1;
}
}
void handleLargeList(char cmd) {
if (cmd == 'U') {
if (cursor == 1) {
// 特殊翻页:第一首歌按Up
cursor = n;
pageStart = max(1, n - 3);
} else {
cursor--;
if (cursor < pageStart) {
pageStart = cursor;
}
}
} else {
if (cursor == n) {
// 特殊翻页:最后一首歌按Down
cursor = 1;
pageStart = 1;
} else {
cursor++;
if (cursor > pageStart + 3) {
pageStart = cursor - 3;
}
}
}
}
public:
MP3Player(int totalSongs) : n(totalSongs), cursor(1), pageStart(1) {}
void process(char cmd) {
if (n <= 4) {
handleSmallList(cmd);
} else {
handleLargeList(cmd);
}
}
void display() {
// 显示当前页面
int end = min(pageStart + 3, n);
for (int i = pageStart; i <= end; i++) {
cout << i << " ";
}
cout << endl;
// 显示当前选中歌曲
cout << cursor << endl;
}
};
int main() {
int n;
string commands;
cin >> n >> commands;
MP3Player player(n);
for (char cmd : commands) {
player.process(cmd);
}
player.display();
return 0;
}
import java.util.*;
public class Main {
static class MP3Player {
private int n; // 总歌曲数
private int cursor; // 当前光标位置(1-based)
private int pageStart; // 当前页面起始歌曲编号(1-based)
public MP3Player(int totalSongs) {
this.n = totalSongs;
this.cursor = 1;
this.pageStart = 1;
}
private void handleSmallList(char cmd) {
if (cmd == 'U') {
cursor = (cursor == 1) ? n : cursor - 1;
} else {
cursor = (cursor == n) ? 1 : cursor + 1;
}
}
private void handleLargeList(char cmd) {
if (cmd == 'U') {
if (cursor == 1) {
cursor = n;
pageStart = Math.max(1, n - 3);
} else {
cursor--;
if (cursor < pageStart) {
pageStart = cursor;
}
}
} else {
if (cursor == n) {
cursor = 1;
pageStart = 1;
} else {
cursor++;
if (cursor > pageStart + 3) {
pageStart = cursor - 3;
}
}
}
}
public void process(char cmd) {
if (n <= 4) {
handleSmallList(cmd);
} else {
handleLargeList(cmd);
}
}
public void display() {
int end = Math.min(pageStart + 3, n);
for (int i = pageStart; i <= end; i++) {
System.out.print(i + " ");
}
System.out.println();
System.out.println(cursor);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String commands = sc.next();
MP3Player player = new MP3Player(n);
for (char cmd : commands.toCharArray()) {
player.process(cmd);
}
player.display();
}
}
class MP3Player:
def __init__(self, total_songs):
self.n = total_songs # 总歌曲数
self.cursor = 1 # 当前光标位置(1-based)
self.page_start = 1 # 当前页面起始歌曲编号(1-based)
def handle_small_list(self, cmd):
if cmd == 'U':
self.cursor = self.n if self.cursor == 1 else self.cursor - 1
else:
self.cursor = 1 if self.cursor == self.n else self.cursor + 1
def handle_large_list(self, cmd):
if cmd == 'U':
if self.cursor == 1:
# 特殊翻页:第一首歌按Up
self.cursor = self.n
self.page_start = max(1, self.n - 3)
else:
self.cursor -= 1
if self.cursor < self.page_start:
self.page_start = self.cursor
else:
if self.cursor == self.n:
# 特殊翻页:最后一首歌按Down
self.cursor = 1
self.page_start = 1
else:
self.cursor += 1
if self.cursor > self.page_start + 3:
self.page_start = self.cursor - 3
def process(self, cmd):
if self.n <= 4:
self.handle_small_list(cmd)
else:
self.handle_large_list(cmd)
def display(self):
# 显示当前页面
end = min(self.page_start + 3, self.n)
print(' '.join(map(str, range(self.page_start, end + 1))))
# 显示当前选中歌曲
print(self.cursor)
# 处理输入
n = int(input())
commands = input().strip()
player = MP3Player(n)
for cmd in commands:
player.process(cmd)
player.display()
算法及复杂度
- 算法:模拟
- 时间复杂度: O ( m ) \mathcal{O}(m) O(m),其中 m m m 是命令的长度
- 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1),只需要常数额外空间
这个解法通过模拟MP3播放器的行为,维护当前光标位置和页面起始位置,根据不同情况处理上下键的操作。代码结构清晰,分别处理了歌曲数量小于等于4和大于4的情况。
解题思路
这道题要求在DNA序列中找出GC-Ratio最高的子串,需要注意以下几点:
- GC-Ratio = (G和C的个数) / 子串长度
- 子串长度固定为输入的N
- 如果有多个子串的GC-Ratio相同,输出第一个
解题步骤:
- 使用滑动窗口遍历所有长度为N的子串
- 对每个子串计算GC-Ratio
- 记录最大GC-Ratio及其对应的子串
- 如果遇到相同的GC-Ratio,保持第一个找到的子串不变
代码
#include <iostream>
#include <string>
using namespace std;
string findMaxGCRatio(string dna, int n) {
if (dna.length() < n) return "";
// 计算第一个窗口的GC数量
int maxGC = 0;
int currentGC = 0;
for (int i = 0; i < n; i++) {
if (dna[i] == 'G' || dna[i] == 'C') {
currentGC++;
}
}
maxGC = currentGC;
int maxStart = 0;
// 滑动窗口
for (int i = 1; i <= dna.length() - n; i++) {
// 移除窗口左边的字符的贡献
if (dna[i-1] == 'G' || dna[i-1] == 'C') {
currentGC--;
}
// 添加窗口右边新字符的贡献
if (dna[i+n-1] == 'G' || dna[i+n-1] == 'C') {
currentGC++;
}
// 更新最大值
if (currentGC > maxGC) {
maxGC = currentGC;
maxStart = i;
}
}
return dna.substr(maxStart, n);
}
int main() {
string dna;
int n;
while (cin >> dna >> n) {
cout << findMaxGCRatio(dna, n) << endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
public static String findMaxGCRatio(String dna, int n) {
if (dna.length() < n) return "";
// 计算第一个窗口的GC数量
int maxGC = 0;
int currentGC = 0;
for (int i = 0; i < n; i++) {
if (dna.charAt(i) == 'G' || dna.charAt(i) == 'C') {
currentGC++;
}
}
maxGC = currentGC;
int maxStart = 0;
// 滑动窗口
for (int i = 1; i <= dna.length() - n; i++) {
if (dna.charAt(i-1) == 'G' || dna.charAt(i-1) == 'C') {
currentGC--;
}
if (dna.charAt(i+n-1) == 'G' || dna.charAt(i+n-1) == 'C') {
currentGC++;
}
if (currentGC > maxGC) {
maxGC = currentGC;
maxStart = i;
}
}
return dna.substring(maxStart, maxStart + n);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String dna = sc.next();
int n = sc.nextInt();
System.out.println(findMaxGCRatio(dna, n));
}
}
}
def find_max_gc_ratio(dna, n):
if len(dna) < n:
return ""
# 计算第一个窗口的GC数量
current_gc = sum(1 for c in dna[:n] if c in 'GC')
max_gc = current_gc
max_start = 0
# 滑动窗口
for i in range(1, len(dna) - n + 1):
# 更新当前窗口的GC数量
if dna[i-1] in 'GC':
current_gc -= 1
if dna[i+n-1] in 'GC':
current_gc += 1
# 更新最大值
if current_gc > max_gc:
max_gc = current_gc
max_start = i
return dna[max_start:max_start+n]
while True:
try:
dna = input().strip()
n = int(input())
print(find_max_gc_ratio(dna, n))
except:
break
算法及复杂度
- 算法:滑动窗口
- 时间复杂度: O ( N ) \mathcal{O}(N) O(N),其中 N N N 是DNA序列的长度
- 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1),只需要常数额外空间
2万+

被折叠的 条评论
为什么被折叠?



