【Java版oj】day24洗牌、MP3光标位置

目录

 一、洗牌

(1)原题再现

(2)问题分析

(3)完整代码

 二、MP3光标位置

(1)原题再现

(2)问题分析

(3)完整代码


 一、洗牌

(1)原题再现

洗牌_网易有道笔试题_牛客网

        洗牌在生活中十分常见,现在需要写一个程序模拟洗牌的过程。 现在需要洗2n张牌,从上到下依次是第1张,第2张,第3张一直到第2n张。首先,我们把这2n张牌分成两堆,左手拿着第1张到第n张(上半堆),右手拿着第n+1张到第2n张(下半堆)。接着就开始洗牌的过程,先放下右手的最后一张牌,再放下左手的最后一张牌,接着放下右手的倒数第二张牌,再放下左手的倒数第二张牌,直到最后放下左手的第一张牌。接着把牌合并起来就可以了。 例如有6张牌,最开始牌的序列是1,2,3,4,5,6。首先分成两组,左手拿着1,2,3;右手拿着4,5,6。在洗牌过程中按顺序放下了6,3,5,2,4,1。把这六张牌再次合成一组牌之后,我们按照从上往下的顺序看这组牌,就变成了序列1,4,2,5,3,6。 现在给出一个原始牌组,请输出这副牌洗牌k次之后从上往下的序列。

 

输入描述:

        第一行一个数T(T ≤ 100),表示数据组数。对于每组数据,第一行两个数n,k(1 ≤ n,k ≤ 100),接下来有2n行个数a1,a2,...,a2n(1 ≤ ai ≤ 1000000000)。表示原始牌组从上到下的序列。

输出描述:

        对于每组数据,输出一行,最终的序列。数字之间用空格隔开,不要在行末输出多余的空格。

示例1

3

3 1

1

2

3

4

5

6

3 2

1

2

3

4

5

6

2 2

1

1

1

1

输出

1 4 2 5 3 6

1 5 4 3 2 6

1 1 1 1

(2)问题分析

        本题重要的是先把一次洗牌的结果找出,根据要求k为几,就用for循环几次。

        一次洗牌的步骤:首先把所有牌分成两部分,用两个数组保存。第一幅牌数组下标是从0到所有牌的一半(len/2),第二副牌数组下标是从len/2到len。然后定义一个结果数组,用来存放洗完牌后的结果,根据题目要求,其实就是把第一副牌放在第一个位置,第二副牌放到第二个位置,一次交叉。因为结果数组下标是从0开始的,所以下标能整除2的地方就用来存放第一副牌,不能整除的存放第二副牌。注意:i等于1的时候表示,第二副牌中的第一张牌(位置下标为0)存放在结果数组的第二个位置(位置下标是1)。

(3)完整代码

import java.util.Scanner;

/*
 * 洗牌
 */
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int times = sc.nextInt();
        while (times-- > 0) {
            int n = sc.nextInt();
            int k = sc.nextInt();
            int []cards = new int [2 * n];
            for (int i = 0; i < 2 * n; i++) {
                cards[i] = sc.nextInt();
            }
            for (int i = 0; i < k; i++) {
                cards = shuffleOneCard(cards);
            }
            for (int i = 0; i < 2 * n; i++) {
                if (i == 2 * n - 1) {
                    System.out.println(cards[i]);
                    break;
                }
                System.out.print(cards[i] + " ");
            }
        }
    }
    public static int[]shuffleOneCard(int[]cards) {
        int len = cards.length;
        int []oneCards = new int [len / 2];
        int []twoCards = new int [len / 2];
        int []res = new int [len];
        for (int i = 0; i < len / 2; i++) {
            oneCards[i] = cards[i];
        }
        for (int i = 0; i < len / 2; i++) {
            twoCards[i] = cards[i + len / 2];
        }
        for (int i = 0; i < len; i++) {
            if (i % 2 == 0) {
                res[i] = oneCards[i / 2];
            } else {
                res[i] = twoCards[(i - 1) / 2];
            }
        }
        return res;
    }
}

 二、MP3光标位置

(1)原题再现

MP3光标位置__牛客网
来源:牛客网
 

        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

(2)问题分析

        这道题看似很长很复杂,其实只要根据题目要求,分情况把所有可能的结果列举出来就行了。

分情况:

1.歌曲总数1小于等于4

2.歌曲总数大于4------>特殊翻页-------->从一页往上翻页跳到最后一页

                            |                         |----->从一页往上翻页跳到最后一页

                            |---->普通翻页-------->往上翻页

                                                     |----->往下翻页

                                                     |----->不用翻页

        因为需要输出每页上的所有歌曲,所以需要start变量记录每页第一个歌曲的位置,index表示光标的位置。

(3)完整代码

import java.util.*;
/*
 * MP3光标位置
 */
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        String str = sc.next();

        if (num <= 4) {
            lowerFour(num, str);
        } else {
            upFour(num, str);
        }
    }
    //翻页
    public static void upFour(int num, String str) {
        //特殊页面
        int index = 1; //光标
        int start = 1; //每页开始第一个

        for (int i = 0; i < str.length(); i++) {
            if (start == 1 && index == 1 && str.charAt(i) == 'U') {
                index = num;
                start = num - 3;
                continue;
            }
            if (start == num - 3 && index == num && str.charAt(i) == 'D') {
                index = 1;
                start = 1;
                continue;
            }
            //普通翻页

            //往上翻页
            if (start == index && str.charAt(i) == 'U') {
                start--;
                index--;
                continue;
            }
            //往下翻页
            if (start + 3 == index && str.charAt(i) == 'D') {
                start++;
                index++;
                continue;
            }
            //不用翻页
            if (str.charAt(i) == 'U') {
                index--;
            }
            if (str.charAt(i) == 'D') {
                index++;
            }
        }

        System.out.print(start + " " + (start + 1) + " " + (start + 2) + " " +
                         (start + 3));
        System.out.println();
        System.out.println(index);
    }

    //<4
    public static void lowerFour(int num, String str) {
        int index = 1; //光标
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == 'U') {
                if (index == 1) {
                    index = num;
                    continue;
                } else {
                    index--;
                    continue;
                }
            }
            if (str.charAt(i) == 'D') {
                if (index == num) {
                    index = 1;
                    continue;
                } else {
                    index++;
                    continue;
                }
            }
        }

        for (int i = 1; i <= num; i++) {
            if (i == num) {
                System.out.println(i);
                break;
            }
            System.out.print(i + " ");
        }
        System.out.println(index);
    }

}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小熊爱吃软糖吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值