题目
有一座保密大楼,你从 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));
}
}
}
结论
本题的解答比较“笨”,算法思路本人不大擅长,求大佬提供更好的简便的解答。欢迎讨论,谢谢三连。