首页 > 试题广场 >

MP3光标位置

[编程题]MP3光标位置
  • 热度指数:132849 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

MP3 Player因为屏幕较小,显示歌曲列表的时候每屏只能显示几首歌曲,用户要通过上下键才能浏览所有的歌曲。为了简化处理,假设每屏只能显示4首歌曲,光标初始的位置为第1首歌。

现在要实现通过上下键控制光标移动来浏览歌曲列表,控制逻辑如下:

  1. 歌曲总数<=4的时候,不需要翻页,只是挪动光标位置。

光标在第一首歌曲上时,按Up键光标挪到最后一首歌曲;光标在最后一首歌曲时,按Down键光标挪到第一首歌曲。

其他情况下用户按Up键,光标挪到上一首歌曲;用户按Down键,光标挪到下一首歌曲。

2. 歌曲总数大于4的时候(以一共有10首歌为例):


特殊翻页:屏幕显示的是第一页(即显示第1 4首)时,光标在第一首歌曲上,用户按Up键后,屏幕要显示最后一页(即显示第7-10首歌),同时光标放到最后一首歌上。同样的,屏幕显示最后一页时,光标在最后一首歌曲上,用户按Down键,屏幕要显示第一页,光标挪到第一首歌上。

一般翻页:屏幕显示的不是第一页时,光标在当前屏幕显示的第一首歌曲时,用户按Up键后,屏幕从当前歌曲的上一首开始显示,光标也挪到上一首歌曲。光标当前屏幕的最后一首歌时的Down键处理也类似。

其他情况,不用翻页,只是挪动光标就行。

数据范围:命令长度,歌曲数量
进阶:时间复杂度:,空间复杂度:

输入描述:

输入说明:
1 输入歌曲数量
2 输入命令 U或者D



输出描述:

输出说明
1 输出当前列表
2 输出当前选中歌曲

示例1

输入

10
UUUU

输出

7 8 9 10
7
import java.util.*;
import java.io.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader bu = new BufferedReader(new InputStreamReader(System.in)  );
        //光标范围为1-4,光标值为1到输入的值max
        Integer max = (Integer.parseInt(bu.readLine()));
        String[] data = bu.readLine().split("");
        Integer index = 1;
        Integer currentPosition = 1;
        for (int i = 0; i < data.length; i++) {
            if (data[i].equals("U")) {
                if (index - 1 < 1) {
                    // 翻到了最上面,自动光标定位到最大4,光标值为max
                    index = max;
                    currentPosition = 4;
                } else {
                     // 光标值--
                    index--;
                    // 假设可以直接正常上翻
                    currentPosition--;
                    if (currentPosition < 1) {
                        // 如果翻完了过后光标位置小于了1,重置为1
                        currentPosition = 1;
                    }
                }
            } else {
                if (index + 1 > max) {
                    // 翻到了最下面,自动光标定位到最大1,光标值为1
                    index = 1;
                    currentPosition = 1;
                } else {
                    // 假设可以直接下翻
                    currentPosition++;
                    // 光标值++
                    index++;
                    if (currentPosition > 4) {
                         // 如果翻完了过后光标位置大于了4,重置为4
                        currentPosition = 4;
                    }
                }
            }
        }
        show(index, max, currentPosition);

    }

    public static void show(Integer index, Integer max, Integer currentPosition) {

        List<Integer> str = new ArrayList<>();
        StringBuilder  ss = new StringBuilder("");
        int res = index;
        // 输出光标位置前面的数字
        for (int i = 1; i < currentPosition; i++) {
            index = index - 1;
            if (index > 0) {
                // 如果这个值超出了合理范围不添加
                str.add(index);
            }

        }
        index = res;
        // 输出光标位置以及后面的数字
        for (int i = 0; i <= 4 - currentPosition; i++) {
            if (index <= max) {
                // 如果这个值超出了合理范围不添加
                str.add(index);
            }
            index = index + 1;
        }
        Collections.sort(str);
        for (int i = 0; i < str.size(); i++) {
            ss.append(str.get(i)).append(" ");
        }
        System.out.println(ss);
        System.out.println(res);
    }


}

发表于 2024-11-03 21:26:16 回复(0)

以为是青铜,结果是王者……这题目的坑实在太多。我的思路是用两个指针来分别表示显示列表最上方和光标。光标的移动是循环的,而列表指针需要明确三种情况:随光标一起上移或下移、列表上移到最后四条或列表下移到前四条、连续下移后突然上移(或反之)。最后输出的时候要考虑不足四条的情况。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int count = in.nextInt();
        String keys = in.next();
        // pointer指向当前光标,top指向当前页面最上方
        // pointer不为1,是为了计算方便。可以把pointer看成是一个数组的索引
        int pointer = 0, top = 0;
        for (char k : keys.toCharArray()) {
            // 光标指针循环进退位
            if (k == 'U') {
                pointer = (pointer - 1 + count) % count;
                if (pointer > count - 4) {  // 此时指针指向最后四首歌
                    top = count - 4;
                } else if (pointer < top) {  // 此时指针指向列表最上方,列表需要一起上移
                    top = pointer;
                }  // 其他情况,指针在列表内移动,top不动
            }
            if (k == 'D') {
                pointer = (pointer + 1) % count;
                if (pointer < 4) {  // 指针从第一屏开始,重置列表
                    top = 0;
                } else if (pointer - 3 > top) {  // 指针指向列表最下方,列表一起下移
                    top = pointer - 3;
                }
            }
        }
        if (count < 4) {
            top = 0;  // 如果不到四条,不用麻烦了
        }
        for (int i = 1; i <= count && i <= 4; i++) {  // 输出
            if (i == count || i == 4) {
                System.out.println(top+i);
            } else {
                System.out.print((top+i)+" ");
            }
        }
        System.out.println(pointer + 1);
    }
}
发表于 2024-10-01 20:09:11 回复(0)
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 处理多个 case
            int a = in.nextInt();
            String b = in.next();
            int st = 1;
            int sign = 1;
            for (int i = 0 ; i < b.length(); i++) {
                if (b.charAt(i) == 'D') {
                    if (st == a) {
                        st = 1;

                    } else st++;
                    if (st == 1) sign = 1;
                    else if (sign < 4)sign++;
                } else if (b.charAt(i) == 'U') {
                    if (st == 1) {
                        st = a;
                    } else st--;
                    if (st == a) sign = a<4?a:4;
                    else if (sign > 1)sign--;
                }
                //System.out.println(st + " " + sign);
            }
            //System.out.println(st + " " + sign);
            for (int i = st -sign+1 ; i <= st - sign + (a<4?a:4); i++) System.out.print(i + " ");
            System.out.println("");
            System.out.println(st);
           
    }
}
发表于 2024-09-07 03:53:00 回复(0)
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int pageSize = in.nextInt();//总页数
        int pagePoint = 1;//光标位置
        int pageStart = 1;//当前页面第一个元素

        //引入page变量是因为测试案例中可能存在歌曲数量少于4的情况
        //在计算首页或尾页跳转时,这样可以更通用的涵盖小于4的情况
        int page = 4;//页面大小,默认为4
        String str = in.next();
        if(pageSize < 4){
            page = pageSize;//如果页面大小少于4,需要赋值
        }
        for (char ch : str.toCharArray()) {
            //指令为U的情况
            if (ch == 'U') {
                //当光标在当前页面第一项时
                if (pagePoint == pageStart) {
                    //第一项为1需要特殊处理
                    if (pagePoint == 1) {
                        //计算需要跳转到哪里
                        pageStart = pageSize - page + 1;
                        pagePoint = pageSize;
                    } else {
                        pagePoint--;
                        pageStart--;
                    }
                //当页面光标不在当前页面第一项时
                } else {
                    pagePoint--;
                }
            //指令为D的情况
            } else {
                //当页面光标在当前页面最后一项时
                if (pagePoint == pageStart + page - 1) {
                    //页面光标在总数的最后一项时需要跳回第一项
                    if (pagePoint == pageSize) {
                        pagePoint = 1;
                        pageStart = 1;
                    } else {
                        pagePoint++;
                        pageStart++;
                    }
                //当页面光标不在当前页面最后一项时
                } else {
                    pagePoint++;
                }
            }
        }
        //打印结果
        for (int i = pageStart; i < pageStart + page; i++) {
            System.out.print(i + " ");
        }
        System.out.print("\n" + pagePoint);
    }
}
发表于 2024-07-07 19:29:16 回复(0)
我觉得还能改改
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int songCount = Integer.parseInt(in.nextLine());
        String operations = in.nextLine();
        ViewPort viewPort = new ViewPort(songCount);
        viewPort.execute(operations);
        System.out.println(viewPort.getCurrentView());
        System.out.println(viewPort.getCurrentSong());
    }
}

class ViewPort {
    private final int songCount;
    private int currentSong = 0;
    private int top = 0;
    private int bottom = 3;

    public ViewPort(int songCount) {
        this.songCount = songCount;
    }

    private void up() {
        currentSong--;
        if (currentSong < 0) {
            // move to the last song
            currentSong = songCount - 1;
            bottom = songCount - 1;
            if (songCount < 4) {
                top = 0;
            } else {
                top = songCount - 4;
            }
        } else if (currentSong < top) {
            top--;
            bottom--;
        }
    }

    private void down() {
        currentSong++;
        if (currentSong >= songCount) {
            // move to the first song
            currentSong = 0;
            top = 0;
            if (songCount < 4) {
                bottom = songCount - 1;
            } else {
                bottom = 3;
            }
        } else if (currentSong > bottom) {
            top++;
            bottom++;
        }
    }

    public void execute(String operations) {
        for (int i = 0; i < operations.length(); i++) {
            char operation = operations.charAt(i);
            switch (operation) {
                case 'U':
                    up();
                    break;
                case 'D':
                    down();
                    break;
            }
        }
    }

    public String getCurrentView() {
        StringBuilder sb = new StringBuilder();
        for (int i = top; i <= bottom; i++) {
            sb.append(i + 1).append(" ");
        }
        return sb.toString().trim();
    }

    public int getCurrentSong() {
        return currentSong + 1;
    }
}


发表于 2024-06-23 11:13:19 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int total = Integer.parseInt(sc.nextLine());
        String operations = sc.nextLine();
        int[] data = new int[total];
        for (int i = 0; i < total; i++) {
            data[i] = i + 1;
        }
        int size = total < 4 ? total : 4;
        int[] win = new int[size];
        for (int i = 0; i < size; i++) {
            win[i] = i + 1;
        }
        int[] initWin = new int[size];
        System.arraycopy(win, 0, initWin, 0, win.length);
        int cur = 0;
        for (int i = 0; i < operations.length(); i++) {
            char oper = operations.charAt(i);
            if (oper == 'U') {
                if (win[cur] == data[0]) {
                    // 第一个数,total>4,窗口到底,光标到底
                    // 第一个数,total<=4,窗口不动,光标到len-1
                    if (total > 4) {
                        for (int j = 0; j < 4; j++) {
                            win[j] = data[total - 1 - (3 - j)];
                        }
                        cur = 3;
                    } else {
                        cur = total - 1;
                    }
                } else {
                    // 光标=0,窗口上移,光标不动
                    // 光标>0,窗口不动,光标-1
                    if (cur == 0) {
                        moveWin(win, -1);
                    } else {
                        cur--;
                    }
                }
            } else if (oper == 'D') {
                if (win[cur] == data[total - 1]) {
                    // 最后一个数:窗口重置,光标重置
                    System.arraycopy(initWin, 0, win, 0, initWin.length);
                    cur = 0;
                } else {
                    if (cur < 3) {
                        // 光标<3:窗口不动,光标+1
                        cur++;
                    } else {
                        // 光标=3(底部),窗口下移1,光标不动
                        moveWin(win, 1);
                    }
                }
            } else {
                throw new RuntimeException("invalid oper");
            }
        }
        for (int v : win) {
            System.out.print(v + " ");
        }
        System.out.println();
        System.out.println(win[cur]);
    }

    private static void moveWin(int[] win, int dt) {
        for (int i = 0; i < win.length; i++) {
            win[i] = win[i] + dt;
        }
    }
}

编辑于 2024-03-22 01:10:37 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int cnt = in.nextInt();
        in.nextLine();
        String mv = in.nextLine();
        int finalCursor = 1;
        int pageSize = cnt >= 4 ? 4 : cnt;
        int curPageCursor = 1;//光标在当前页的位置,只能是1-pageSize
        //得到最终光标所在位置
        for (int i = 0; i < mv.length(); i++) {
            if(mv.charAt(i) == 'D') {
                finalCursor++;
                //如果光标所在位置小于页大小,则位置加1,否则为不同向下翻页,位置不变
                if (curPageCursor < pageSize) {
                    curPageCursor++;
                }
                if (finalCursor > cnt) {
                    finalCursor = 1;
                    curPageCursor = 1;//向下特殊翻页,光标挪到开始
                }
            } else if (mv.charAt(i) == 'U') {
                finalCursor--;
                //如果光标所在当前页位置大于1,则位置减一,否则为普通向上翻页,位置不变
                if (curPageCursor > 1) {
                    curPageCursor--;
                }
                if (finalCursor < 1) {
                    finalCursor = cnt;
                    curPageCursor = pageSize;//向上特殊翻页,光标位置挪到最后
                }
            }
        }
        //通过当前光标所在页中的位置和所在序号可以计算出当前页显示的所有序号
        for (int i = finalCursor - curPageCursor + 1; i <= finalCursor + (pageSize - curPageCursor); i++) {
            System.out.print(i + " ");
        }
        System.out.println();
        System.out.println(finalCursor);
    }
}

编辑于 2024-02-06 12:15:46 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        in.nextLine();
        int k = 1;
        String op = in.nextLine();
        int start = 1;
        int end = Math.min(4, n);
        for (int i = 0; i < op.length(); i++) {
            if (op.charAt(i) == 'U') {
                if (k == 1) {
                    k = n;
                }else {
                    k--;
                }
            } else {
                k = k % n + 1;
            }
            if (k < start) {
                start = k;
                end = start + 3;
            } else if (k > end) {
                end = k;
                start = end - 3;
            }
        }
        for (int i = start; i <= end; i++) {
            System.out.print(i + " ");
        }
        System.out.println("\n" + k);
    }
}

发表于 2023-11-26 01:49:31 回复(0)
直接维护两个int值,一个记录当前页第一个index,另一个记录当前歌曲的index
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n=in.nextInt();
        in.nextLine();
        char[] ins=in.nextLine().toCharArray();
        int first=0;
        int curr=0;
        for(int i=0;i<ins.length;i++){
            if(ins[i]=='U'){
                curr=(curr+n-1)%n;
                if(curr<first){
                    first=curr;
                }else if(curr>first+3){
                    first=curr>=3?curr-3:0;
                }
            }else if(ins[i]=='D'){
                curr=(curr+n+1)%n;
                if(curr>first+3){
                    first=curr>=3?curr-3:0;
                }else if(curr<first){
                    first=curr;
                }
            }
        }
        int i=1;
        int l=Math.min(n,4);
        while(i<l){
            System.out.print((first+i++)+" ");
        }
        System.out.println((first+l));
        System.out.print(curr+1);
    }
}


发表于 2023-09-08 01:14:29 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void func(int n,String str){
        //初始时光标所在位置
        int first=1;
        int mouse=1;
        char []index=str.toCharArray();
        if(n<=4){
            for(int i=0;i<index.length;i++){
                //光标在第一首歌曲上时,按Up键光标挪到最后一首歌曲
                if(mouse==1&&index[i]=='U'){
                    mouse=n;
                }
                //光标在最后一首歌曲时,按Down键光标挪到第一首歌曲
                else if(mouse==n&&index[i]=='D'){
                    mouse=1;
                }
                //用户按Up键,光标挪到上一首歌曲
                else if(index[i]=='U'){
                    mouse--;
                }
                //用户按Down键,光标挪到下一首歌曲
                else{
                    mouse++;
                }
            }
            for(int i=1;i<n;i++){
                System.out.print(i+" ");
            }
            System.out.println(n);
            System.out.println(mouse);
        }else{
            for(int i=0;i<index.length;i++){
                // 屏幕显示的是第一页(即显示第1 – 4首)时,光标在第一首歌曲上,用户按Up键后,屏幕要显示最后一页(即显示第7-10首歌),同时光标放到最后一首歌上
                if(first==1&&mouse==1&&index[i]=='U'){
                    mouse=n;
                    first=n-3;
                }
                // 同样的,屏幕显示最后一页时,光标在最后一首歌曲上,用户按Down键,屏幕要显示第一页,光标挪到第一首歌上。
                else if(first==mouse-3&&mouse==n&&index[i]=='D'){
                    first=1;
                    mouse=1;
                }
                //屏幕显示的不是第一页时,光标在当前屏幕显示的第一首歌曲时,用户按Up键后,屏幕从当前歌曲的上一首开始显示,光标也挪到上一首歌曲。
                else if(first!=1&&mouse==first&&index[i]=='U'){
                    first--;
                    mouse--;
                }
                // 光标当前屏幕的最后一首歌时的Down键处理也类似
                else if(mouse!=n&&first==mouse-3&&index[i]=='D'){
                    mouse++;
                    first++;
                }
                // 其他情况,不用翻页,只是挪动光标就行
                else if(index[i]=='U'){
                    mouse--;
                }
                else if(index[i]=='D'){
                    mouse++;
                }
            }
            for(int i=first;i<first+3;i++){
                System.out.print(i+" ");
            }
            System.out.println(first+3);
            System.out.println(mouse);
        }
    }
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        // String tmp=in.next();
        String str=in.next();
        func(n,str);
    }
}

发表于 2023-08-12 22:54:09 回复(0)
就是按照指针是否超出边界来更新显示框的上下界,要注意的就是指针跳转到表头和表尾的时候,给上下界分别重定义,然后按照上下界确定索引之后去截取歌曲数组输出就好。
代码可能比较臃肿,见笑了。
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int n = in.nextInt();
            String str = in.next();
            songList sl = new songList(n);
            sl.control(str, sl);
            sl.show(sl);
        }
    }
}

class songList {
    private int songNumber;
    private int nowSong;
    private int[] showSong;
    private int start = 0;
    private int end = start + 3;

    public songList(int n) {
        this.songNumber = n;
        this.nowSong = 0;
        this.showSong = new int[n];
        for (int i = 0; i < n; i++) {
            showSong[i] = i + 1;
        }
    }

    public void up(songList sl) {
        nowSong--;
        if (nowSong == -1) {
            nowSong = sl.songNumber - 1;
            start = Math.max(songNumber - 4, 0);
            end = songNumber - 1;
        } else if (nowSong == start - 1 && start != 0) {
            start--;
            end--;
        }
    }

    public void down(songList sl) {
        nowSong++;
        if (nowSong == sl.songNumber) {
            nowSong = 0;
            start = 0;
            end = Math.min(3, songNumber - 1);
        } else if (nowSong == end + 1 && end != songNumber - 1) {
            start++;
            end++;
        }
    }

    public void show(songList sl) {
        for (int i = sl.start; i <= sl.end; i++) {
            System.out.print(showSong[i] + " ");
        }
        System.out.println();
        System.out.print(nowSong+1);
    }

    public void control(String s, songList sl) {
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == 'U') {
                up(sl);
            } else if (s.charAt(i) == 'D') {
                down(sl);
            }
        }
    }
}

发表于 2023-06-19 10:55:35 回复(0)
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 str = in.next();
            int index = 1;
            int start = 1;
            int end = Math.min(4,n);
            for(int i = 0 ; i < str.length() ; i++){
                if(str.charAt(i)=='U'){
                    if(index==1){
                        index = n;
                    }else{
                        index--;
                    }
                }else{
                    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);
        }
    }
}

发表于 2023-06-01 10:36:43 回复(0)
import java.util.*;
//cur的变化量只能为1,方向根据op判定
//l的变化量dl只能是0,1,4三种,方向根据op判定
//n<=4时,                    => dl=0
//up时,  cur>l,              => dl=0
//down时,cur<l+3,            => dl=0
//up时,  cur==0,             => dl=4
//down时,cur==n-1,           => dl=4
//up时,  cur!=0, cur=l,      => dl=1
//down时,cur!=n-1, cur==l+3, => dl=1
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int n = in.nextInt();
            String operations = in.next();
            int l =0;
            int cur = 0;
            for (int i = 0; i < operations.length(); i++) {
                int op =operations.charAt(i)=='U'?-1:1;//指定变换方向
                int dl = operations.charAt(i)=='U'?(cur>l?0:(cur==0?4:1)):(cur<l+3?0:(cur==n-1?4:1));
                dl=n<=4?0:dl;
                cur=(cur+n+op)%n;//加了变化量后需要模运算免得超出范围 +n是保证不为负数
                l=(l+n+op*dl)%n;
            }
            int max =Math.min(n,4);
            for (int i = 0; i < max; i++) {
                System.out.print(l+1+i);
                if(i<max-1){
                    System.out.print(" ");
                }else{
                    System.out.println();
                }
            }
            System.out.println(cur+1);
        }
    }
}

发表于 2023-03-22 15:03:46 回复(0)