• 【Day21】每日一题——洗牌


    洗牌_牛客题霸_牛客网

    它的意思是说,给你一份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个栈,依次又从第三个栈弹出元素即可~~

    下面是代码实现

    1. import java.util.*;
    2. import java.util.Stack;
    3. public class Main {
    4. public static void main(String[] args) {
    5. Scanner in = new Scanner(System.in);
    6. int group = in.nextInt();
    7. while (group > 0){
    8. int n = in.nextInt();
    9. int count = in.nextInt();
    10. int[] left = new int[n];
    11. int[] right = new int[n];
    12. for(int i = 0; i < n; i++){
    13. left[i] = in.nextInt();
    14. }
    15. for(int i = 0; i < n; i++){
    16. right[i] = in.nextInt();
    17. }
    18. washCard(left,right,count);
    19. group--;
    20. }
    21. }
    22. //洗牌方法
    23. public static void washCard(int[] left, int[] right, int count){
    24. Stack s1 = new Stack<>();
    25. Stack s2 = new Stack<>();
    26. int n = left.length;
    27. int[] ret = new int[2 * n];
    28. for(int j = 0; j < count; j++){
    29. //把left和right分别push进s1,s2
    30. for(int i = 0; i < n; i++){
    31. s1.push(left[i]);
    32. }
    33. for(int i = 0; i < n; i++){
    34. s2.push(right[i]);
    35. }
    36. Stack s3 = new Stack<>();
    37. for(int i = 0; i < n; i++){
    38. s3.push(s2.pop());
    39. s3.push(s1.pop());
    40. }
    41. for(int i = 0; i < ret.length; i++){
    42. ret[i] = s3.pop();
    43. }
    44. //到这里说明洗完一次牌了,要重新给left 和 right 更新元素
    45. for(int i = 0; i < n; i++){
    46. left[i] = ret[i];
    47. }
    48. for (int i = 0; i < n; i++){
    49. right[i] = ret[n + i];
    50. }
    51. }
    52. for(int x : ret){
    53. System.out.print(x + " ");
    54. }
    55. System.out.println();
    56. }
    57. }

     注意它要求的输入

    先输入多少组数据group

    然后在输入一边手拿的牌数和洗牌的次数

    然后给依次给左手右手赋值n张牌就好了~

    ok,结束~

  • 相关阅读:
    vue中的响应式数据和副作用函数
    Linux操作系统
    心脏出血漏洞复现(CVE-2014-0160)
    SECS/GEM300协议通讯平台
    一文详解 implementation api embed
    C语言重点突破(3)字符串函数与内存函数的介绍
    移动设备软件开发测试
    测试用例的设计方法(全):边界值分析方法
    Jmeter分布式测试的注意事项和常见问题
    互联网时代结束了吗?
  • 原文地址:https://blog.csdn.net/qq_61862008/article/details/127804556