招银编程笔试题

企业面试题-招银编程题

(1)洗牌题目

题目简述

一个牌的数值分别是0,1,2,3,4,5,6,7,8,9;当用户指定一个n,即代表有n张牌,且分别是介于0~9之前的任意数组成。小明把拿到的这n张牌分为两堆,左边一堆,右边一堆,如果n是奇数张牌,就把左堆的牌数比右边多一个;如果牌数是偶数,就左右堆平均分配即可。在洗牌的时候,如果是第奇数此洗牌,就先左边一张牌(默认把牌排成一排从后边取),再拿右边一张牌,依次这样往复的出完牌。如果是偶数次洗牌,则是先从右边堆中取出一张牌,再从左边取出一张牌,依次类推取完牌。最终输出洗完牌的顺序。

举例

如:牌为1 2 3 4 5 6 (此时牌为偶数张)

偶数次洗牌得出的最终牌为:1 4 2 5 3 6

此时再把上述洗后的牌再洗牌(此时就是奇数次洗牌了):5 1 3 4 6 2

输入

第一个数为这个牌有几张(n)牌数,第二个数为洗牌的次数,后边的n个数就是牌的面值,如下

6 1 1 2 3 4 5 6 [解释:7代表7张牌,1 代表第1次洗牌,1 2 3 4 5 6 代表牌面数]

输出

4 1 5 2 6 3

java代码

package ncompanydemos.p1_zhaopin;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author jiyongjia
 * @create 2020/6/22 - 21:59
 * @descp:
 *  > 题目描述:
 *  一个牌的数值分别是0,1,2,3,4,5,6,7,8,9;当用户指定一个n,即代表有n张牌,且分别是介于0~9之前的任意数组成。
 *  小明把拿到的这n张牌分为两堆,左边一堆,右边一堆,如果n是奇数张牌,就把左堆的牌数比右边多一个;如果牌数是偶数,
 *  就左右堆平均分配即可。在洗牌的时候,如果是第奇数此洗牌,就先左边一张牌(默认把牌排成一排从后边取),再拿右边一张牌,
 *  依次这样往复的出完牌。如果是偶数次洗牌,则是先从右边堆中取出一张牌,再从左边取出一张牌,依次类推取完牌。最终输出洗完牌的顺序。
 *  > 举例
 *  如:牌为1 2 3 4 5 6   (此时牌为偶数张)
 *      偶数次洗牌得出的最终牌为:1 4 2  5 3 6
 *      此时再把上述洗后的牌再洗牌(此时就是奇数次洗牌了):5 1 3 4 6 2
 *  > 输入
 *      第一个数为这个牌有几张(n)牌数,第二个数为洗牌的次数,后边的n个数就是牌的面值,如下
 *      6 1 1 2 3 4 5 6     [解释:7代表7张牌,1 代表第1次洗牌,1 2 3 4 5 6 代表牌面数]
 *  > 输出
 *      4 1 5 2 6 3
 *
 */
public class Exam01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请按要求输入:");
        int total = scanner.nextInt();  //总牌数
        int cishu = scanner.nextInt();  //洗牌的次数

        //存储牌面数
        int[] arr = new int[total];
        for (int i = 0; i < total; i++) {
            arr[i] = scanner.nextInt();
        }

        //调用方法
        int[] res = shuffle(total, cishu, arr);
        System.out.println("输出:");
        System.out.println(Arrays.toString(res));
    }

    //洗牌
    private static int[] shuffle(int total, int cishu, int[] arr) {
        int leftIndex; //指向左堆的最后一个元素
        int rightIndex; //指向右堆的最后一个元素

        int[] res = new int[total];
        int index = arr.length - 1;//在新数组中添加元素的index
        //1 如果是偶数的牌数,就分成平均的两堆
        if (total % 2 == 0) {
            leftIndex = arr.length / 2 - 1;
            rightIndex = arr.length - 1;

            int count = arr.length / 2;
            while (count > 0 && (leftIndex >= 0 && rightIndex <= arr.length - 1)) {
                //1.1 判断奇数次洗牌的时候,先出左牌
                if (cishu % 2 == 1) {
                    res[index--] = arr[leftIndex--];  //先出左堆
                    res[index--] = arr[rightIndex--]; //再出右堆
                } else { //1.2 判断偶数次洗牌的时候,先出右边堆牌
                    res[index--] = arr[rightIndex--];  //先出右堆
                    res[index--] = arr[leftIndex--]; //再出左堆
                }
            }

        } else {//2 如果是奇数次的牌数,就分成左边比右边多一个的两堆
            leftIndex = arr.length / 2;
            rightIndex = arr.length - 1;

            int count = arr.length / 2;
            while (count > 0 && (leftIndex >= 0 && rightIndex <= arr.length - 1)) {
                //2.1 判断奇数次洗牌的时候,先出左牌
                if (cishu % 2 == 1) {
                    res[index--] = arr[leftIndex--];  //先出左堆
                    res[index--] = arr[rightIndex--]; //再出右堆
                    //左边多的那张牌出出来
                    res[index--] = arr[leftIndex]; //此时不减了,再减1就越界
                } else { ////2.2 判断偶数次洗牌的时候,先出右边堆牌
                    res[index--] = arr[rightIndex--];  //先出右堆
                    res[index--] = arr[leftIndex--]; //再出左堆

                    //左边多的那张牌出出来
                    res[index--] = arr[leftIndex]; //此时不减了,再减1就越界
                }
            }
        }
        return res;
    }
}

输出验证:

验证1:

输入:6 1 1 2 3 4 5 6 (模拟奇数次洗牌)

image-20200622222624241

验证2:

输入:6 2 1 2 3 4 5 6 (模拟偶数次洗牌)

image-20200622222700041