一、题目描述

跳房子,也叫跳飞机,是一种世界性的儿童游戏。

游戏参与者需要分多个回合按顺序跳到第1格直到房子的最后一格,然后获得一次选房子的机会,直到所有房子都被选完,房子最多的人获胜。

跳房子的过程中,如果有踩线等违规行为会结束当前回合,甚至可能倒退几步。

假设房子的总格数是count,小红每回合可能连续跳的步数都放在数据steps中,请问数组中是否有一种步数的组合,可以让小红三个回合跳到最后一格?如果有,请输出索引和最小的步数组合,数据保证索引和最小的步数组合是唯一的。

注意:数组中的步数可以重复,但数组中的元素不能重复使用。

二、输入描述

第一行输入为房子总格数count,它是整数类型int。

第二行输入为每回合可能连续跳过的步数,它是整数数组类型。

三、输出描述

返回索引和最小满足要求的步数组合。

注意:顺序保持steps中的原有顺序。

四、补充说明

  • count <= 10000;
  • 3 <= steps.length <= 10000;
  • -100000 <= steps[i] <= 100000;

五、解题思路

这道题的【题目描述】优点复杂,说的也不是很清晰。

简而言之,就是:

第一行输入一个数count;

第二行输入若干个数steps;

将第二行中的数字,以任意组合的方式(保证三个回合跳到最后一格),等于count即可,看看一共有多少种,然后选出索引和最小的那一组数据,按顺序输出即可

万丈高楼平地起,稳扎稳打,先理清思路,找准方向,再动手。

  1. 输入房子总格数count;
  2. 输入每回合可能连续跳过的步数;
  3. 递归选出索引和最小的那一组数据;
    • 遍历steps数组中的数字,每三个数字进行依次递归;
    • 如果不满足条件,将第三个数字删除,再添加一个新的数字;
    • 再比较小红跳的步数集合是否等于count;
    • 循环往复
  4. 小红跳的步数集合等于count 且 选出索引和最小的那一组数据;
  5. 返回索引和最小满足要求的步数组合;

六、Java算法源码

// 最小索引和public static int min = 100000;// 三个回合跳到最后一格public static int three = 3;// 房子总格数countpublic static int count;// 选出索引和最小的那一组数据public static List<Integer> minIndexList;public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 房子总格数countcount = Integer.valueOf(sc.nextLine());// 每回合可能连续跳过的步数int[] steps = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();// 选出索引和最小的那一组数据getMinSteps(steps, three, new ArrayList<>(), new ArrayList<>(), 0);// 返回索引和最小满足要求的步数组合System.out.println(minIndexList.toString());}/** * 选出索引和最小的那一组数据 * * @param steps steps数组 * @param step步数 * @param list小红跳的步数集合 * @param indexList 小红跳的步数的索引集合 * @param index 当前步数索引 */public static void getMinSteps(int[] steps, int step, List<Integer> list, List<Integer> indexList, int index) {// 三个回合跳到最后一格if (step == 0) {int total = 0;int indexTotal = 0;// 三个回合跳到最后一格for (int i = 0; i < three; i++) {total += list.get(i);// 计算索引和indexTotal += indexList.get(i);}// 小红跳的步数集合等于count 且 选出索引和最小的那一组数据if (total == count && indexTotal < min) {// 符合要求的小红跳的步数集合System.out.println("符合要求的小红跳的步数集合:"+list);// 下角标之和System.out.println("下角标之和:"+indexTotal);min = indexTotal;minIndexList = new ArrayList<Integer>(list);}} else {// 遍历steps数组for (int i = index; i < steps.length; i++) {// 小红跳的步数集合list.add(steps[i]);// 小红跳的步数的索引集合indexList.add(i);// 选出索引和最小的那一组数据getMinSteps(steps, step - 1, list, indexList, i + 1);// 遍历steps数组中的数字,每三个数字进行依次递归,如果不满足条件,将第三个数字删除,再添加一个新的数字,再比较小红跳的步数集合是否等于count,循环往复list.remove(list.size() - 1);indexList.remove(indexList.size() - 1);}}}

感觉很麻烦,能不能再优化优化?

// 最小索引和private static int min = Integer.MAX_VALUE;// 三个回合跳到最后一格private static final int three = 3;// 房子总格数countprivate static int count;// 选出索引和最小的那一组数据private static List<Integer> minIndexList;public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 房子总格数countcount = sc.nextInt();sc.nextLine();// 读取换行符int[] steps = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();minIndexList = new ArrayList<>();getMinSteps(steps, new ArrayList<>(), 0, 0);System.out.println(minIndexList);}/** * 选出索引和最小的那一组数据 * * @param steps 每回合可能连续跳过的步数数组 * @param currentSteps当前已跳的步数集合 * @param currentIndex当前步数索引和 * @param sum 当前步数总和 */public static void getMinSteps(int[] steps, List<Integer> currentSteps, int currentIndex, int sum) {if (currentSteps.size() == three) {if (sum == count && currentIndex < min) {System.out.println("符合要求的小红跳的步数集合:"+currentSteps);System.out.println("下角标之和:"+currentIndex);min = currentIndex;minIndexList = new ArrayList<>(currentSteps);}return;}for (int i = 0; i < steps.length; i++) {// 尝试添加步数currentSteps.add(steps[i]);// 递归调用getMinSteps(steps, currentSteps, currentIndex + i, sum + steps[i]);// 回溯,移除最后一个步数currentSteps.remove(currentSteps.size() - 1);}}

完美!

七、效果展示

1、输入

15
1,9,4,25,10,8,7,5

2、输出

[1, 4, 10]

3、说明

符合条件的步数集合有

[1, 9, 5]

它的下角标之和为:0 + 1 + 7 = 8

[1, 4, 10]

它的下角标之和为:0 + 2 + 4 = 6

因为 6<8,故输出[1, 4, 10]。

下一篇:华为OD机试真题 Java 实现【比赛评分】【2023 B卷 100分】,附详细解题思路

本文收录于,华为OD机试(JAVA)(2022&2023)

本专栏包含了最新最全的2023年华为OD机试真题,有详细的分析和Java解答。已帮助1000+同学顺利通过OD机考。专栏会持续更新,每天在线答疑。