每日一题——MP3光标位置
本系列主要记录,我在刷题过程中的一些值得总结归纳的题
题目描述
MP3 Player因为屏幕较小,显示歌曲列表的时候每屏只能显示几首歌曲,用户要通过上下键才能浏览所有的歌曲。为了简化处理,假设每屏只能显示4首歌曲,光标初始的位置为第1首歌。
现在要实现通过上下键控制光标移动来浏览歌曲列表,控制逻辑如下:
- 歌曲总数<=4的时候,不需要翻页,只是挪动光标位置。
光标在第一首歌曲上时,按Up键光标挪到最后一首歌曲;光标在最后一首歌曲时,按Down键光标挪到第一首歌曲。
其他情况下用户按Up键,光标挪到上一首歌曲;用户按Down键,光标挪到下一首歌曲。
- 歌曲总数大于4的时候(以一共有10首歌为例):
特殊翻页:屏幕显示的是第一页(即显示第1 – 4首)时,光标在第一首歌曲上,用户按Up键后,屏幕要显示最后一页(即显示第7-10首歌),同时光标放到最后一首歌上。同样的,屏幕显示最后一页时,光标在最后一首歌曲上,用户按Down键,屏幕要显示第一页,光标挪到第一首歌上。
一般翻页:屏幕显示的不是第一页时,光标在当前屏幕显示的第一首歌曲时,用户按Up键后,屏幕从当前歌曲的上一首开始显示,光标也挪到上一首歌曲。光标当前屏幕的最后一首歌时的Down键处理也类似。
其他情况,不用翻页,只是挪动光标就行。
数据范围:命令长度1≤s≤100 ,歌曲数量 1≤n≤150
进阶:时间复杂度: O(n) ,空间复杂度: O(n)
输入描述:
输入说明:
1 输入歌曲数量
2 输入命令 U或者D
输出描述:
输出说明
1 输出当前列表
2 输出当前选中歌曲
示例1
输入:
10
UUUU
复制
输出:
7 8 9 10
7
题目分析
这个是一道典型的滑动窗口问题,所谓的滑动窗口问题就是,用队列出队和入队操作来达到一个显示内容的变化。只不过是要进行一定的特别判断而已,因为题目中谈到,在第一页的时候,要翻到最后一页的最后一个歌曲,当你翻到最后一页的时候还要翻回第一页:
类似于这种有一个框可以不断对内容进行框选,进行展示。明白了具体框架,我们还要对一些具体实现进行讨论,就比如具体显示我明白了,那它怎么来模拟光标呢,翻页的逻辑是怎么样的呢??我们可以这样来想,我们不是只是为了来确定光标的位置么,不妨用这个队列的头当作MP3窗口的起始点,锚定,如果要输出页面就从,队头取出四个元素进行输出就行了,然后把队尾当成要移动的光标,来执行命令,就可以了。
推理成立,实践开始;
代码实现
#include<string>
#include <iostream>
using namespace std;
//建立队列
int n;
int hh = 1;//队头
int tt = 1;//队尾
void up_judge()
{
tt--;//光标上移
if(hh == 1 && tt < hh)//如果是第一页就翻到最后一个元素
{
hh = n >= 4? n - 3: 1;//在这里对是不是大于四 进行判断,看是否跳转页面
tt = n;//让光标指向末尾
}
else
{
if(tt < hh) hh = tt;//如果队尾在对头的前面就要让锚定点向前走一个,让显示减少
}
}
void down_judge()
{
tt++;//光标后移
if(tt > n)
{
hh = tt = 1;//如果是到了最后向下翻,回到第一页
}
else {
if(tt - hh + 1 > 4) hh++;//如果是一般翻页就让窗口向后显示
}
}
int main() {
string order;
cin >> n;
cin >> order;//输入命令
//初始化
for(int i = 0;i < order.size();i++)//遍历命令
{
if(order[i] == 'U')
{
up_judge();
}
else
{
down_judge();
}
}
for(int j = hh,i = 1;i <= 4 && j <= n;i++,j++)
{
cout << j << ' ' ;//因为队头其实是窗口的锚定点,所以包括它在内的后四个元素就是,当前窗口显示
}
cout << endl;
cout << tt;//因为数字是连续的所以队尾的指向也是对应位置的元素,而且我们也是用队尾模拟的光标,所以可以
return 0;
}
// 64 位输出请用 printf("%lld")
可以看到的是,我并没有真的开一个数组来模拟实现队列,而只是用了两个下标,利用队列的思想来进行模拟的。因为本题的数字是连续的,所以可以直接将队头队尾的位置当作元素进行输出,因为我的对头队尾是从1开始到n。
后记
其实单调队列也是在解题中的常用思想,所以多加练习,争取掌握。
最后附上罗老师的话和大家共勉
人最大的痛苦,就是无法跨越知道和做到的鸿沟。
队头队尾的位置当作元素进行输出,因为我的对头队尾是从1开始到n。
后记
其实单调队列也是在解题中的常用思想,所以多加练习,争取掌握。
最后附上罗老师的话和大家共勉
人最大的痛苦,就是无法跨越知道和做到的鸿沟。