题目描述
洗牌在生活中十分常见,现在需要写一个程序模拟洗牌的过程。
现在需要洗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次之后从上往下的序列。
eg:
输入:
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
以下是本篇文章正文内容,下面案例可供参考
解题思路
注意题目:
洗牌:先右手再放左手,从下往上洗牌
输出:从上往下输出
eg:1 2 3 4 5 6
左手:1 2 3(索引:0 1 2)
右手:4 5 6(索引:3 4 5)
经过一次洗牌:1 4 2 5 3 6
索引从0开始,我们不难发现:
原来在0位置---->0位置
原来在1位置---->2位置
原来在2位置---->4位置
原来在3位置---->1位置
原来在4位置---->3位置
原来在5位置---->5位置
得出规律:
i---->2*i
i+n---->2i+1
完成一次洗牌操作
代码如下
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int groups = sc.nextInt();
for (int i = 0; i < groups; i++) {
int n = sc.nextInt();
int k = sc.nextInt();
int[] cards = new int[2*n];
for (int j = 0; j < 2*n ; j++) {
cards[j] = sc.nextInt();
}
playCard(cards,n,k);
}
}
}
/**
* 洗牌操作
* @param cards 牌面数组
* @param n 牌数的一半
* @param k 洗牌次数
*/
public static void playCard(int[] cards,int n,int k){
for (int i = 0; i < k; i++) {
//一次洗牌的过程
int[] newCards = new int[cards.length];
//遍历编号为0~n-1的牌
for (int j = 0; j < n; j++) {
newCards[2*j] = cards[j];// i-->2i
newCards[2*j+1] = cards[j+n];//i+n-->2i+1
}
cards = newCards;
}
//从上往下打印
printCards(cards);
}
/**
* 输出:以空格相隔,最后一个后无空格
* @param cards
*/
private static void printCards(int[] cards) {
for (int i = 0; i < cards.length-1; i++) {
System.out.print(cards[i]+" ");//先输出前面的
}
System.out.println(cards[cards.length-1]);//输出最后一个数,无空格
}
}