部门优化和邀请码检测面试题——Java解法

部门优化

某公司内有 4 个项⽬组,项⽬组 A、B、C、D,项⽬组A现有10人,项⽬组B现有7人,项⽬组C现 有5人,项⽬组D现有4人。为了实现跨项⽬组协作,公司决定每⽉从⼈数最多的项⽬组中抽调 3 ⼈ 出来,到其他剩下 3 组中,每组 1 人,这称之为一次调整优化(亦即经过第⼀次调整后,A组有7 人,B组有8人,C组有6人,D组有5人)。 那么请问,经过十年的优化调整后,各项目组各有几人? 编程求解该问题,并思考是否为最优解。

解题思路

最直观的解题思路就是,每次都进行一次优化,根据优化规则一直优化120次。

每次优化其实就是从数组中选出最大值,然后最大值-3,其他元素+1。

代码逻辑实现:

public class Solution {
    public static void main(String[] args) {
        test1();
    }

    public static void test1(){
        //初始数组
        int[] arr={10,7,5,4};
		//一个月优化一次,十年一共120次
        for (int i = 0; i <120 ; i++) {
            arr=optimize(arr);
        }
        //打印优化十年后的结果
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }

    }

    /**
     * 优化的逻辑
     * @param arr 目标数组
     * @return 优化后的数组
     */
    private static int[] optimize(int[] arr){
        int index=getMaxIndex(arr);
        for (int i = 0; i < arr.length; i++) {
            if(index==i){
                arr[i]-=3;
            }else{
                arr[i]+=1;
            }
        }
        return arr;
    }

    /**
     * 获取数组最大值的索引
     * @param arr 目标数据
     * @return 最大值的索引
     */
    private static int getMaxIndex(int [] arr){
        int max=0;
        int index=0;
        for (int i = 0; i < arr.length; i++) {
            if(arr[i]>max){
                max=arr[i];
                index=i;
            }
        }
        return index;
    }
}

总结规律之后发现,这个并非最优解。前几次的结果如下所示:

优化1次:10 7 5 4

优化2次:7 8 6 5

优化3次:8 5 7 6

优化4次:5 6 8 7

优化5次:6 7 5 8

优化6次:7 8 6 5

此后的结果一直在7,8,6,5之间变换。除去第一次的结果,从第二次开始每4个数据之后开始重复。也就是说一共119次优化,前116次优化之后结果为7 8 6 5,再优化三次,得出结果为6 7 5 8。

邀请码检测

某产品的⽤户注册邀请码为⼀串有⼩写字⺟和数字组成的字符串,字符串⻓度为16。当⽤户数据邀 请码的时候,系统需要对邀请码做有效性验证,假设验证规则如下: 1、 从序列号最后⼀位字符开始,逆向将奇数位(1、3、5等等)相加; 2、从序列号最后⼀位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去 9),再求和; 3、将奇数位总和加上偶数位总和,结果可以被10整除; 4、⼩写字⺟对应数值,可由下⾯键值对确定; [(a,1), (b,2), (c,3)…,(i,9), (j,1), (k, 2)…],亦即,按字⺟顺序,1-9循环。 输⼊:输⼊16位字符串,表示邀请码 输出:输出“ok”或者“error”

解题思路

这个题真没什么好说的,按题目做就行了。主要是要知道ASCLL码对应的值

public class inviteCodeSolution {
    public static void main(String[] args) {
        String s = "123456789123456C";
        System.out.println(isVerify(s));
    }

    /**
     * 对校验结果进行格式化
     * @param s 传入的邀请码
     * @return 如果合法则为ok,否则为error
     */
    public static String isVerify(String s) {
        boolean result = false;
        try {
            result = verify(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result ? "ok" : "error";
    }

    /**
     * 校验邀请码是否合法
     * @param s 传入的邀请码
     * @return true合法,false不合法
     * @throws Exception 传入的数据包含除数字和小写字母以外的字符
     */
    public static boolean verify(String s) throws Exception {
        char[] chars = s.toCharArray();
        int sumOdd = 0, sumEven = 0;
        //逆序遍历

        for (int i = chars.length - 1; i >= 0; i--) {
            //如果是偶数位
            if (i % 2 == 0) {

                sumEven += getMapData(chars[i]) > 4 ? ((getMapData(chars[i]) * 2) - 9) : (getMapData(chars[i]) * 2);

            } else {
                //奇数位
                sumOdd += getMapData(chars[i]);
            }
        }

        System.out.println("偶数和:" + sumEven + ",奇数和:" + sumOdd);
        return (sumEven + sumOdd) % 10 == 0;
    }

    /**
     * 获取映射的值
     *
     * @param c 传入的字符
     * @return c的实际值
     */
    public static int getMapData(char c) throws Exception {
        int result;
        //如果是小写字母,则按规则映射成数字
        if (c >= 97 && c <= 122) {
            result = (c - 96) % 9;
        } else if (c >= 48 && c <= 57) {
            result = c - 48;
        } else {
            //非数字和小写字母则抛出异常
            throw new Exception("数据错误");
        }
        return result;
    }
}
posted @ 2020-10-09 17:31  六层楼  阅读(922)  评论(0编辑  收藏  举报