华为OD机试 - 乘坐保密电梯 - 逻辑分析

题目

有一座保密大楼,你从 0 楼到达指定楼层 m,必须这样的规则乘坐电梯:

给定一个数字序列,每次根据序列中的数字 n,上升 n 层或者下降 n 层,前后两次的方向必须相反,规定首次的方向向上,自行组织序列的顺序按规定操作到达指定楼层。

求解到达楼层的序列组合,如果不能到达楼层,给出小于该楼层的最近序列组合。

1 2 6 和 6 2 1 都满足条件,按照先处理大值的规则,输出结果为 6 2 1。

样例

输入
5 3
1 2 6
输出
6 2 1

题目理解

1.本题存在争议点:前后两次必须相反,但没有要求输入的数组是否可以为负数,如果可以,则必然有前后不相反的,据此反推,是否可以理解为输入只能为正数?但因为题目和样例不足,搁置
2.目标是M层,然后给定一串数据,这一串数据进行一加一减后,假设最终达到M,那么,如果减去M,则为0,所以,可以理解为输入的数据求和再加上M,除以2,得到的是中位数(是这个名词么),然后输入数据的加数和减数可以等于这个中位数

代码

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

/**
 * @Desc: 乘坐保密电梯
 * @Auther:chenShunGuo
 * @Date: 2024/5/31 14:19
 */
public class Test013 {
    public static void main(String[] args) {
        try{
            Scanner sc = new Scanner(System.in);
            String oneS = sc.nextLine();
            String secondS = sc.nextLine();
            String[] split = oneS.split(" ");
            int count = Integer.parseInt(split[1]);
            List<Integer> list = new ArrayList<Integer>();
            String[] splitSecond = secondS.split(" ");
            // 对输入和目标进行求和,如果能到目标,则一加一减的最终结果是总和的一半
            // 5 + 1 + 2 + 6 = 14 均数是14/2 = 7
            // 因本人时间问题,未优化负数的逻辑,当存在输入为负数时,都正向增加最小负数,在输出时再减去负数,以保证程序正确
            int min = 0;
            for (int i = 0; i < count; i++) {
                int temp = Integer.parseInt(splitSecond[i]);
                list.add(Integer.parseInt(splitSecond[i]));
                if (temp < min) {
                    min = temp;
                }
            }
            // 有余数则说明只能靠近
            Collections.sort(list);
            // 优先最大的数字
            Collections.reverse(list);
            int sum = Integer.parseInt(split[0]);
            if (min < 0) {
                sum = sum - min;
            }
            for (int i = list.size() - 1; i >= 0; i--) {
                if (min < 0) {
                    list.set(i, list.get(i) - min);
                }
                sum += list.get(i);
            }

            List<Integer> addList = new ArrayList<>();
            List<Integer> otherList = new ArrayList<>();
            int target = sum / 2;
            getList(count, target, list, addList, otherList);
            if (addList.size() < otherList.size()) {
                // 加集比减集少,则第一位需要置换一下
                int index0 = list.get(0);
                int index1 = list.get(1);
                list.set(0, index1);
                list.set(1, index0);
                addList = new ArrayList<>();
                otherList = new ArrayList<>();
                getList(count, target, list, addList, otherList);
            }

            StringBuffer buffer = new StringBuffer();
            int index = 0;
            for (int i = 0; i < addList.size(); i++) {
                if (min < 0) {
                    index += addList.get(i) + min;
                    buffer.append(addList.get(i) + min).append(" ");
                    if (i < otherList.size()) {
                        index -= otherList.get(i) + min;
                        buffer.append(otherList.get(i) + min).append(" ");
                    }
                } else {
                    index += addList.get(i);
                    buffer.append(addList.get(i)).append(" ");
                    if (i < otherList.size()) {
                        index -= otherList.get(i);
                        buffer.append(otherList.get(i)).append(" ");
                    }
                }
            }
            System.out.println(buffer.substring(0, buffer.length() - 1));
            System.out.println(index);
        }  catch (Exception e) {
            System.out.println("Error");
        }
    }

    private static void getList(int count, int target, List<Integer> list,
        List<Integer> addList, List<Integer> otherList) {
        int temp = 0;
        int addSize = count / 2;
        if (count % 2 == 1) {
            addSize += 1;
        }
        for (int i = 0; i < count; i++) {
            if (addList.size() < addSize) {
                // 进到这里说明加集还不够,但是如果集合进行未到一半,而加权已经超过均数,则后续无法给加集添加
                // 所以要给减集
                if (i < count / 2 && temp + list.get(i) >= target) {
                    otherList.add(list.get(i));
                    continue;
                }
                if (temp + list.get(i) <= target) {
                    addList.add(list.get(i));
                    temp += list.get(i);
                    continue;
                }
            }
            otherList.add(list.get(i));
        }
    }
}

结论

本题的解答比较“笨”,算法思路本人不大擅长,求大佬提供更好的简便的解答。欢迎讨论,谢谢三连。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值