部门优化和邀请码检测面试题——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;
}
}