题解 | #MP3光标位置#

MP3光标位置

https://www.nowcoder.com/practice/eaf5b886bd6645dd9cfb5406f3753e15

这道题应该可以不用迭代器的,但我最开始用了迭代器,就想着把它做对了,结果就遇到迭代器指针的坑,然后调了好长时间,好累,一度想要放弃,但最终总算好了,也是这个机会是把迭代器指针了取数了相关的搞明白了。

总结:

1.ListIterator中的previous()返回值是当前迭代器的cursor左边的值,next()方法返回值是cursor右边的值

2.迭代器的使用场景,应该是迭代趋势不变的情况下,例如一直向next取值,或者一直向previous取值,如果一会儿next一会儿previous的话,会很混乱,最后把自己搞死,当然如果对迭代器足够了解的话,也可以,就是伤脑筋。

3.如果用cursor右边的值表示当前选中歌曲,那么在接到"D"指令时,应该先用next()把cursor移到下一首歌曲之前,然后再调一次next()取值,取完值之后,为了保证下一次迭代时cursor在当前选中歌曲之前,就得调一次previous把cursor恢复:

接到D指令之前:|歌曲1 歌曲2 歌曲3 歌曲4 , 当前选中歌曲为歌曲1,此时若用next()取到的不是下一首歌,而是歌曲1

所以要先next()一下把指针移到歌曲2之前:歌曲1 |歌曲2 歌曲3 歌曲4 ,这时候为了取到歌曲2就得再调一次next()取它的返回值,调完之后指针变成这样了:歌曲1 歌曲2 |歌曲3 歌曲4,这会导致下一次迭代时,认为当前选中歌曲是歌曲3,实际上我们是歌曲2,为了避免如此,就调一个previous()把指针恢复到歌曲2。

总之可以这么说:为了取到指针右边的值以便将其设置为当前选中歌曲,但是又不改变指针位置(不影响下一次迭代),就每次取完值之后再调一次previous恢复指针位置。见如下代码中66,67,68三行。

4.若有关联迭代器,最好不要再用ArrayList的remove和add方法修改ArrayList中的值,这很可能导致的报错。原因如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.ListIterator;
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 a = Integer.parseInt(in.nextLine());
            String b = in.nextLine();
            new Main().MP3iter(a, b);
        }
    }
  //思路:建立两个列表及两个各自的迭代器,一个是歌曲总列表有n个值(用来记录当前选中的是哪首歌),一个是显示列表只有最多4个值(用来记录当前显示列表),每次取一个命令,根据命令是U或者D来处理两个迭代器
    void MP3iter(int n, String cmd) {
        ArrayList<Integer> arr = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            arr.add(i, i + 1);
        }
        ListIterator<Integer> arri = arr.listIterator(0);//所有歌曲迭代器,默认选中为第一首歌
        ArrayList<Integer> out = new ArrayList<>();
        Arrays.stream(new int[] {1, 2, 3, 4}).forEach(o->out.add(o));
        ListIterator<Integer> outi = out.listIterator(0);//当前显示列表迭代器
        int now = 1;//表示当前选中歌曲,默认第一首歌,此时不要用next()取now的初始值,否则会把指针移到第二首歌那里,一定要用的话,就再用previous回退一下
        while (cmd.length() > 0) {
            char nowcmd = cmd.charAt(0);
            int nowp = now;
            if (nowcmd == 'U') {
			  //当命令为U时取now值
                if (arri.previousIndex() == -1) {//若执行U前选中的是第一首歌
                    arri = arr.listIterator(n);//手动把歌曲迭代器的指针设置到最后一首歌的右边
                    now = arri.previous().intValue();//执行previous后指针在最后一首歌左边,使我们想要的选中该歌的状态
                } else {
                    now = arri.previous().intValue();//若执行U前选中的不是歌曲1,则直接前移指针
                }
			  //当命令为U时取显示列表
                if (outi.previousIndex() == -1) {//若执行U前选中的是显示列表的第一条
                    if (nowp == 1) {//若该条还是第一首歌,则显示列表全部替换为最后一页
                        out.set(3, n);
                        out.set(2, n - 1);
                        out.set(1, n - 2);
                        out.set(0, n - 3);
                        outi = out.listIterator(3);//显示列表指针设置为选中第四行
                    } else {//若该条不是第一首歌,则显示列表第一条设置为now,最后一条去掉,显示列表指针位置不变
                        int out0 = out.get(0);
                        int out1 = out.get(1);
                        int out2 = out.get(2);
                        out.set(0, now);
                        out.set(1, out0);
                        out.set(2, out1);
                        out.set(3, out2);
                    }


                } else {//若执行U前选中的不是显示列表的第一条
                    outi.previous();

                }

            }
            if (nowcmd == 'D') {
			   //当命令为D时取now值:
                if (arri.nextIndex() == arr.size() - 1) {//若执行D命令前选中的是最后一首歌
                    arri = arr.listIterator(0);//手动把指针放到第一首歌,手动设置now值
                    now = 1;
                } else {//若执行D命令前选中的不是最后一首歌
                    arri.next();//把指针移到下一首歌之前
                    now = arri.next().intValue();//取下一首歌的值
                    arri.previous();//取完值后恢复指针
                }
			  //当命令为D时取显示列表:
                if (outi.nextIndex() == 3) {//若执行D前选中的是显示列表的第四条
                    if (nowp == n) {//若执行D前选中的是最后一页最后一首歌,显示列表全部替换为首页
                        outi = out.listIterator(0);//手动将选中歌曲设置为列表第一条
                        out.set(0, 1);
                        out.set(1, 2);
                        out.set(2, 3);
                        out.set(3, 4);
                    } else {//若执行D前选中的不是最后一页最后一首歌,列表选中项不变,列表内容去头加尾
                        int out1 = out.get(1);
                        int out2 = out.get(2);
                        int out3 = out.get(3);
                        out.set(0, out1);
                        out.set(1, out2);
                        out.set(2, out3);
                        out.set(3, now);

                    }
                } else {//若执行D前选中的不是显示列表的第四条
                    outi.next();
                }
            }
            if (cmd.length() == 1) {//为防止取substring时数组越界,发现执行完最后一个命令后,直接退出循环
                break;
            }
            cmd = cmd.substring(1);

        }
        if (n < 4) {//当歌曲总数小于4时,显示列表是固定的1->n
            for (int cf = 1; cf <= n; cf++) {
                System.out.printf("%d ", cf);
            }
            System.out.println();
        } else {
            out.forEach(ff->System.out.printf("%d ", ff));
            System.out.println();
        }
        System.out.println(now);
    }
}

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务