华为机试-064-中等-HJ64.MP3光标位置
一、描述
MP3 Player因为屏幕较小,显示歌曲列表的时候每屏只能显示几首歌曲,用户要通过上下键才能浏览所有的歌曲。为了简化处理,假设每屏只能显示4首歌曲,光标初始的位置为第1首歌。
现在要实现通过上下键控制光标移动来浏览歌曲列表,控制逻辑如下:
歌曲总数<=4的时候,不需要翻页,只是挪动光标位置。
光标在第一首歌曲上时,按Up键光标挪到最后一首歌曲;光标在最后一首歌曲时,按Down键光标挪到第一首歌曲。
其他情况下用户按Up键,光标挪到上一首歌曲;用户按Down键,光标挪到下一首歌曲。
2. 歌曲总数大于4的时候(以一共有10首歌为例):
3. 特殊翻页:屏幕显示的是第一页(即显示第1 – 4首)时,光标在第一首歌曲上,用户按Up键后,屏幕要显示最后一页(即显示第7-10首歌),同时光标放到最后一首歌上。同样的,屏幕显示最后一页时,光标在最后一首歌曲上,用户按Down键,屏幕要显示第一页,光标挪到第一首歌上。
一般翻页:屏幕显示的不是第一页时,光标在当前屏幕显示的第一首歌曲时,用户按Up键后,屏幕从当前歌曲的上一首开始显示,光标也挪到上一首歌曲。光标当前屏幕的最后一首歌时的Down键处理也类似。
其他情况,不用翻页,只是挪动光标就行。
数据范围:命令长度 1 ≤ s ≤ 100 ,歌曲数量 1 ≤ n ≤ 150
1.1、输入描述
输入说明:
1 输入歌曲数量
2 输入命令 U或者D
1.2、输出描述
输出说明
1 输出当前列表
2 输出当前选中歌曲
二、示例
2.1、示例1
输入:
10
UUUU
输出:
7 8 9 10
7
三、答案(java)
3.1、方法一
解题思路:
模拟整个过程处理。情况分为歌曲数小于等于4和大于4两种情况,每种情况都要考虑特殊翻页、一般翻页、其他。用n表示歌曲总数,first表示当前页面的第一首歌,num表示当前选中的歌。
算法流程:
当歌曲数小于等于4时:特殊向上翻页,移动光标到最后一首歌;特殊向上翻页,移动光标到第一首歌;一般向上翻页,光标向上移动一格;一般向下翻页,光标向下移动一格;
当歌曲数大于4时:特殊向上翻页,光标移动到最后一首歌,最后一页第一首歌为n-3;特殊向下翻页,光标移动到第一首歌,第一页第一首歌为1;一般向上翻页,光标向上移一格,当前页第一首歌和光标位置相同;一般向下翻页,光标向下移一格,当前页第一首歌位置也向下移一格;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
String cmd = sc.next();
parseCmd(cmd, n);
}
}
public static void parseCmd(String str, int n) {
// 页面数据大小,默认4
int pageSize = 4;
// 页面的歌曲大小,最大为4
if (n < pageSize) {
pageSize = n;
}
// 根据指令移动current光标,可以当作歌曲编号
int current = 1;
// 记录光标在页面中的位置pageIndex,即歌曲编号
int pageIndex = 1;
for (int i=0; i < str.length(); i++) {
// 上移
if (str.charAt(i) == 'U') {
// 特殊情况,当前光标在歌曲中第一首
if (current == 1) {
// 从第一行上移,移动到最后的歌曲
current = n;
// 光标在页面的位置,
pageIndex = pageSize;
// 一般情况,即光标不在第一行
} else {
// 光标上移
current--;
if (pageIndex != 1) {
pageIndex--;
}
}
} else {
// 下移
// 已经到最后一首歌曲,光标到第一首歌曲
if (current == n) {
current = 1;
pageIndex = 1;
} else {
// 非最后一行,则光标下移即可
current++;
if (pageIndex != pageSize) {
pageIndex++;
}
}
}
}
// 计算光标前后数字个数
int next = pageSize - pageIndex;
int pre = pageSize - 1 - next;
// 打印页面
String page = "";
// 从当前光标前一个元素开始向前打印
for (int i = pre; i>0; i--) {
page += (current-i) + " ";
}
page += current + " ";
for (int i=1; i<=next; i++) {
page += (current + i) + " ";
}
// 去除尾部空格
page = page.substring(0, page.length()-1);
System.out.println(page);
// 打印当前光标
System.out.println(current);
}
}
四、答案(python 3)
4.1、方法一
保姆级别的代码分享,虽然不是很简洁。
刚开始思路根本不清晰,看了大佬们的解法自己重构了一个,几番调整总算全部通过,分享一下。
n<5的情况比较简单,只用确定光标位置,没有翻页操作,不做分析。
n>4的情况分析如下:
问题点:如果确定当前页面的 4 首歌-------只需要确定当前页面某一首歌的索引位置,就能确定整个页面的四首歌
问题点:如何确定光标位置--------光标始终在显示页面的某一首歌上,因此其取值范围可固定为:1,2,3,4
问题点:Up 操作在什么位置特殊--------当光标位于页面第1首歌时,Up操作会刷新页面歌曲,实现一般翻页;当显示1~4首歌且光标位于1时,Up操作实现特殊翻页,页面歌曲变为显示 n-3~ n 首歌,光标位置位置变为4
问题点:Down 操作在什么位置特殊--------当光标位于页面第4首歌时,Down操作会刷新页面歌曲,实现一般翻页;当显示 n-3~ n 首歌且光标位于4时,Down操作实现特殊翻页,页面歌曲变为显示 1~4 首歌,光标位置位置变为1
其他:当光标不处于以上情况时,Up 、Down 操作只会实现光标位置变化,当前页面的4首歌曲不会变化
#!/usr/bin/python
# -*- coding: UTF-8 -*-
while True:
try:
n = int(input()) # 储存歌曲总数
s = input().strip() # 储存操作
l = []
for i in range(1, n + 1): # 建立歌曲列表(非必要,我这里是为了统一输出,完全可以不用列表直接输出)
l.append(i)
# 关键变量
f = 1 # f 用于指示当前页面第1首歌曲的索引位置,即应对问题 1
p = 1 # p 用于指示当前页面光标所在位置,即应对问题 2 ,一页最多显示4首歌,所以 p 的取值范围在 1,2,3,4 之中
if n < 5: # 第一种情况,歌曲总数最多一页,没有翻页操作,比较简单,实现方法很多,这里不做介绍
for i in s:
if i == 'U':
if p == 1:
p = n
else:
p -= 1
if i == 'D':
if p == n:
p = 1
else:
p += 1
# 第二种情况,歌曲总数多于一页,有翻页操作,详见代码注释
else:
for i in s: # 依次遍历操作
if i == 'U': # 判断操作是否为 Up
if f == 1 and p == 1: # 问题点3:特殊翻页处理;当且仅当,当前页面为歌曲1 2 3 4(f = 1)且光标位于位置 1(p = 1)时,从第一页翻到最后一页
f = n - 3 # 最后一页的4首歌为:n-3 n-2 n-1 n,因此 f = n-3
p = 4 # 特殊翻页过后,光标直接指向当前页面最后一首歌,即 p = 4
elif p == 1: # 问题点3:一般翻页操作; 当光标位于当前页面第一首歌时,Up操作不会改变光标位置,即p=1不变,而向上翻页使得f = f-1
f -= 1
else: # 问题点5:普通操作。当光标不在当前页面第一首歌时,Up操作只会改变光标位置(p = p-1),不会改变f
p -= 1
if i == 'D': # Down 操作同理,理解特殊翻页,一般翻页 f 和 p的取值即变化,即可进行
if f == n - 3 and p == 4:
f = 1
p = 1
elif p == 4:
f += 1
else:
p += 1
for i in l[f - 1:f + 4 - 1]: # 输出当前页,列表索引从0开始,因此变量 f 需要减 1
print(i, end=' ')
print()
print(f + p - 1)
except:
break