
目录
- 专栏导读
- 一、题目描述
- 二、输入描述
- 三、输出描述
- 1、输入
- 2、输出
- 3、说明
 
- 四、解题思路
- 五、Java算法源码
- 六、效果展示
- 1、输入
- 2、输出
- 3、说明
 
 
华为OD机试 2024C卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷+C卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
小明负责公司年会,想出一个趣味游戏:
屏幕给出1~9任意4个不重复的数字,大家以最快的时间给出这几个数字可拼成的数字从小到大排列位于第N位置的数字,其中N为给出数字中最大的数(如果不到这么多数字,则给出最后一个即可)。
注意:
- 2可以当做5来使用,5也可以当做2来使用进行数字拼接,且屏幕不能同时给出2和5;
- 6可以当做9来使用,9也可以当做6来使用进行数字拼接,且屏幕不能同时给出6和9;
如给出:1,4,8,7,则可以拼接的数字为:
1,4,7,8,14,17,18,41,47,48,71,74,78,81,84,87,147,148,178,187…
那么第N个数字,即第8个数字为41,输出41。
二、输入描述
输入以逗号分隔的4个1~9的数字组成的字符串。
三、输出描述
输出这几个数字可拼成的数字从小到大排列位于第N位置的数字,其中N为给出数字中最大的数。
如果输入的数字不在规定的范围内或有重复,则输出-1
1、输入
1,4,8,7
2、输出
41
3、说明
可以拼接的数字为:
1,4,7,8,14,17,18,41,47,48,71,74,78,81,84,87,147,148,178,187…
那么第N个数字,即第8个数字为41,输出41。
四、解题思路
- 输入4个1~9的数字,升序排序;
- 校验输入合法性; 
  - 如果不足4个数字,则输出-1;
- 输入必须是1~9的数字;
- 不能同时包含2和5;
- 不能同时包含6和9;
 
- 取最大的数N;
- 通过深度优先搜索dfs算法,拼接所有数字,参数依次为(输入的4位数数组、数字是否使用过、拼接的数字)
- 获取组成的数字从小到大排序后第N个数字。
五、Java算法源码
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Test03 {
    static int N = 0;
    static StringBuilder builder = new StringBuilder();
    static int ret = -1;
    static Map<Integer,Integer> map = new HashMap<>();
    static {
        map.put(2,5);
        map.put(5,2);
        map.put(6,9);
        map.put(9,6);
    }
    /**
     * 2和5可以互换,且不能同时出现
     * 6和9可以互换,且不能同时出现
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 5,7,1,6
        int[] arr = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
        Arrays.sort(arr);// 升序排序 1 5 6 7
        // 校验输入合法性
        if (!checkNum(arr)) {
            System.out.println(-1);
            return;
        }
        N = arr[3];// 取最大的数
        boolean[] usedArr = new boolean[4];
        dfs(arr, usedArr, "");
        // 获取组成的数字从小到大排序后第N个数字
        System.out.println(getNumInN(builder));
    }
    static String start = "";
    /**
     * @param arr     输入的4位数数组 1 5 6 7
     * @param usedArr 数字是否使用过
     * @param tempNum 拼接的数字
     */
    private static void dfs(int[] arr, boolean[] usedArr, String tempNum) {
        builder.append(tempNum).append(",");
        for (int i = 0; i < arr.length; i++) {
            // 如果当前数用过了,则跳过
            if (usedArr[i]) {
                continue;
            }
            usedArr[i] = true;
            dfs(arr, usedArr, tempNum + arr[i]);
            if(map.containsKey(arr[i])){
                dfs(arr, usedArr, tempNum + map.get(arr[i]));
            }
            usedArr[i] = false;
        }
    }
    private static boolean checkNum(int[] arr) {
        // 如果不足4个数字,则输出-1
        if (arr.length != 4) {
            return false;
        }
        int sum2 = 0;
        int sum6 = 0;
        for (int i = 0; i < arr.length; i++) {
            int n = arr[i];
            // 输入必须是1~9的数字
            if (n < 1 || n > 9) {
                return false;
            }
            // 不能同时包含2和5
            if (n == 2 || n == 5) {
                sum2++;
            }
            // 不能同时包含6和9
            if (n == 6 || n == 9) {
                sum6++;
            }
        }
        if (sum2 > 1 || sum6 > 1) {
            return false;
        }
        return true;
    }
    // 获取组成的数字从小到大排序后第N个数字
    private static int getNumInN(StringBuilder builder) {
        builder.deleteCharAt(0);
        builder.deleteCharAt(builder.length() - 1);
        int[] arr = Arrays.stream(builder.toString().split(",")).mapToInt(Integer::parseInt).toArray();
        Arrays.sort(arr);//升序排序
        return arr[N - 1];
    }
}
六、效果展示
1、输入
1,4,8,7
2、输出
41
3、说明
获取组成的数字从小到大排序后第8个数字:
1,4,7,8,14,17,18,41,47,48,71,74,78,81,84,87,147,148,174,178,184,187…
即为41。

🏆下一篇:华为OD机试 - 最长的顺子 - 感谢@禁止你发言提供的更简便算法(Java 2023 B卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(A卷+B卷+C卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。




















