它的意思是说,给你一份2n张的牌组,左手拿n张,右手拿n张,然后来进行洗牌操作
洗牌的操作是这样的,你的牌组假设是 1 2 3 4 5 6
那么你左手拿3张:1 2 3(第一张牌是1,最后一张牌是3)
右手也拿3张:4 5 6(第一张牌是4,最后一张牌是6)、
分好牌后,现在进行洗牌:先放右手的牌,先放最后一张(也就是6),然后再放左手的牌(同样是此时的最后一张:3)然后就按照每边都放此时的最后一张牌,然后右左交替即可
然后洗一遍牌后:结果为1 4 2 5 3 6(从第一张牌往下看的结果)
假如又要再洗一遍牌:那么要在上一次洗的牌的基础上来给左手右手分牌
左手此时就拿到了1 4 2
右手就拿到了:5 3 6
再次分好牌后,又继续往复上述的洗牌过程即可~
以上就是题目的规则介绍和基本思路
下面细说解题的法子~
1.首先我们要给一组牌组对吧(1 2 3 4 5 6),那么我们可以选择一个数组来定义这些元素,之后在给左手和右手各分配一半; 但是把因为我们既然要给左手和右手分配一半的牌,那么我们直接给左手数组和右手数组直接赋值就行了,两个数组的长度就是n
2.给左手右手分好牌后,我们就要来洗牌了,咱们直接自定义一个洗牌的方法(washCard)
我们来讲讲洗牌的代码实现
既然我们要左右手放牌,我们可以联想到栈,首先栈的特点是什么呢:先进后出对吧
我们画个图来理解,我们现在把左手和右手的牌各自从上到下放在栈里面
s1表示左手栈,s2表示右手栈,我们分别把左手右手元素push进去后,就上图所示~
我们根据栈后进先出的特点,分别把两个栈,依次右左弹出~
这时候我们再定义一个栈s3,我们把依次弹出的元素push到s3中,咱们根据要求来:先弹出右手的6,再弹出左手3,依次下来就是6 3 5 2 4 1
我们按照这个规则把弹出的元素依次存在s3中,我们会得到下图的s3~
注意!!!!我们把s3搞出来后,你会发现,我们洗第一次牌的结果就是s3从上到下元素排序的结果!!!!
然后我们根据栈的特点依次把s3的元素弹出,我们可以把弹出的元素依次存在一个长度为2n的数组中,数组的结果就是 1 4 2 5 3 6
这样我们就完成了第一次洗牌!!!这不算难对吧?思路到这里是很清晰的~
那么我们再来看特殊情况:假如要洗多次牌呢?
咱们假设要洗2次吧(多次就是把洗牌的过程重复就行了)
我们已经洗好一次了,结果为 1 4 2 5 3 6 了对吧,因为这个结果是用一个数组存的,然后要在这个顺序的基础上再洗一次牌,接下来还是跟之前一样咯,给左手右手各自分一半的牌,这时候左手又拿到牌了:1 4 2 右手拿到:5 3 6
既然我们再次分好牌,只需要再来一遍上述洗牌的过程即可,再分别放在两个栈里面,然后再分别弹出到第3个栈,依次又从第三个栈弹出元素即可~~
下面是代码实现
import java.util.*;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int group = in.nextInt();
while (group > 0){
int n = in.nextInt();
int count = in.nextInt();
int[] left = new int[n];
int[] right = new int[n];
for(int i = 0; i < n; i++){
left[i] = in.nextInt();
}
for(int i = 0; i < n; i++){
right[i] = in.nextInt();
}
washCard(left,right,count);
group--;
}
}
//洗牌方法
public static void washCard(int[] left, int[] right, int count){
Stack<Integer> s1 = new Stack<>();
Stack<Integer> s2 = new Stack<>();
int n = left.length;
int[] ret = new int[2 * n];
for(int j = 0; j < count; j++){
//把left和right分别push进s1,s2
for(int i = 0; i < n; i++){
s1.push(left[i]);
}
for(int i = 0; i < n; i++){
s2.push(right[i]);
}
Stack<Integer> s3 = new Stack<>();
for(int i = 0; i < n; i++){
s3.push(s2.pop());
s3.push(s1.pop());
}
for(int i = 0; i < ret.length; i++){
ret[i] = s3.pop();
}
//到这里说明洗完一次牌了,要重新给left 和 right 更新元素
for(int i = 0; i < n; i++){
left[i] = ret[i];
}
for (int i = 0; i < n; i++){
right[i] = ret[n + i];
}
}
for(int x : ret){
System.out.print(x + " ");
}
System.out.println();
}
}
注意它要求的输入
先输入多少组数据group
然后在输入一边手拿的牌数和洗牌的次数
然后给依次给左手右手赋值n张牌就好了~
ok,结束~