【华为OD题库-039】乘坐保密电梯-java

题目

有一座保密大楼,你从0楼到达指定楼层m,必须这样的规则乘坐电梯:给定一个数字序列,每次根据序列中的数字n上升n层或者下降n层,前后两次操作的方向必须相反,规定首次的方向向上,自行组织序列的顺序按规定操作到达指定楼层。求解到达楼层的序列组合,如果不能到达楼层,给出小于该楼层的最近序列组合。
说明:
操作电梯时不限定楼层范围
必须对序列中的每个项进行操作,不能只使用—部分。
输入描述:
第一行:期望的楼层,取值范围[1,50];序列总个数,取值范围[1,23]
第二行:序列,每个值取值范围[1,50]
输出描述
能够达到楼层或者小于该楼层最近的序列
补充说明:
操作电梯时不限定楼层范围
必须对序列中的每个项进行操作,不能只使用—部分
示例1
输入:
5 3
1 2 6
输出:
6 2 1
说明:
1 2 6
6 2 1
均为可行解,按先处理大值的原则结果为6 2 1

思路

排列组合题,此类问题思路可参考:【JAVA-排列组合】一个套路速解排列组合题
此题来说,有两种思路解题:

  1. 排列思路
  2. 组合思路

排列思路

因为题目说明中有"优先处理大值原则",比如9 8 5 1和9 5 5 4两组数的和相等,按照大值原则应该选择9 8 5 1。所以可以先将原数组从大到小排序,这样在计算排列的时,会优先选择大的数
然后求其全排列,第一个为正,第二个为负…,记录一组排列的和
找到最符合条件的和的组合:
当存在组合的总和与目标值相等时,如果只有一个,直接输出该组合;如果存在多个时,输出第一个即可。(优先输出较大值。因为已经按倒序排列,所以第一个相等的组合一定是优先输出的。)
当不存在组合的总和等于目标值时,找到最接近的总和(只能比目标值小),
输出结果

组合思路

排列的方法有很多冗余计算,效率较低。可以考虑将问题转为组合问题。
设序列和为sum,正数和为positive,负数和为neg,目标为target,那么:
因为:positive+neg=sum;positive-neg<=target
所以:positive<=(sum+target)/2
考虑数组总数为奇数的情况,由于第一个是正数,那么其正数的数量应该为,(nums.length+1)/2;负数的数量为:nums.length/2
所以原来的题目就转化为,在nums中找(nums.length+1)/2个数,使其和<=(sum+target)/2,求sum最大时的组合是多少,存在多个时,按照大值原则输出。
关键在于此种情况存在多个值时,应该怎么判断取哪一个?

比如,nums:4 5 2 5 9 8 5 1,target:7
可能能找到的整数组合为:9 8 5 1或者9 5 5 4两者和都为23,如果取前者,那么8是正数,否则8为负数。组装答案时必须先正后负的形式,前者最符合的情况是9 X 8…,后者最符合的情况是 9 8 5…,很明显后者更符合情况。
所以当两组数同时符合时,判断逻辑应该是根据奇偶位判断,如果是奇数位,越大越好,如果是偶数位,越小越好(越小,说明能够留给负数的值更大,可以排在前面)

根据组合思路,可以找到原nums中应该标记正数的索引集合。从而区分出nums哪些为正,哪些为负
最后,根据正负数集合,先从交替从正、负数集合选择值到最后的结果即可。

题解

排列

package hwod;import java.util.*;
import java.util.stream.Collectors;public class SecurityElevator {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int target = sc.nextInt();int n = sc.nextInt();sc.nextLine();int nums[] = new int[n];for (int i = 0; i < n; i++) {nums[i] = sc.nextInt();}int[] res = securityElevator(nums, target);for (int i = 0; i < res.length; i++) {if (i != 0) System.out.print(" ");System.out.print(res[i]);}}private static int[] res;private static int nearest = Integer.MAX_VALUE;private static int[] securityElevator(int[] nums, int target) {Arrays.sort(nums);LinkedList<Integer> path = new LinkedList<>();int[] used = new int[nums.length];res = new int[nums.length];dfs(nums, used, path, target);return res;}//排列思路解题private static void dfs(int[] nums, int[] used, LinkedList<Integer> path, int target) {if (path.size() == nums.length && target >= 0) {if (target < nearest) {res = path.stream().mapToInt(i -> i).toArray();nearest = target;}}for (int i = nums.length - 1; i >= 0; i--) {if (used[i] == 1) continue; //不能选择自身path.addLast(nums[i]);used[i] = 1;int flag = (path.size() & 1) == 1 ? 1 : -1;dfs(nums, used, path, target - (nums[i] * flag));path.removeLast();used[i] = 0;}}
}

组合

package hwod;import java.util.*;
import java.util.stream.Collectors;public class SecurityElevator {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int target = sc.nextInt();int n = sc.nextInt();sc.nextLine();int nums[] = new int[n];for (int i = 0; i < n; i++) {nums[i] = sc.nextInt();}int[] res = securityElevator(nums, target);for (int i = 0; i < res.length; i++) {if (i != 0) System.out.print(" ");System.out.print(res[i]);}}private static int[] res;private static int nearest = Integer.MAX_VALUE;private static int[] securityElevator(int[] nums, int target) {Arrays.sort(nums);LinkedList<Integer> path = new LinkedList<>();int[] used = new int[nums.length];res = new int[nums.length];dfs(nums, used, path, target);return res;}
private static int[] securityElevator2(int[] nums, int target) {int sum = Arrays.stream(nums).sum();//neg >=(sum - target) / 2//选一半的数,使和<=pos//neg+positive=sum,positive-neg<=target;2*pos-sum<=target,pos<=(sum+target)/2int positive = (sum + target) / 2;Arrays.sort(nums);LinkedList<Integer> path = new LinkedList<>();int[] used = new int[nums.length];//得到正数的索引集合resdfs2(nums, nums.length - 1, path, used, positive);List<Integer> positiveIdxList = Arrays.stream(res).boxed().collect(Collectors.toList());//标记原数组的正负号int[] positives = new int[(nums.length + 1) / 2];int[] negatives = new int[nums.length / 2];int m = 0, n = 0;for (int i = nums.length - 1; i >= 0; i--) {if (positiveIdxList.contains(i)) {positives[m++] = nums[i];} else {negatives[n++] = nums[i];}}//组装正负数,得到答案,先正后负int[] ans = new int[nums.length];for (int i = 0; i < nums.length; i++) {if((i&1)==0)ans[i] = positives[i / 2];else ans[i] = negatives[i / 2];}return ans;}//组合思路解题,在nums中找(nums.length+1)/2个数,使其和<=(sum+target)/2;private static void dfs2(int[] nums, int start, LinkedList<Integer> path, int[] used, int target) {if (target < 0) return;if (path.size() == (nums.length + 1) / 2) {if (target < nearest) {res = path.stream().mapToInt(i -> i).toArray();nearest = target;} else if (target == nearest) {res = getMoreBigger(res, path.stream().mapToInt(i -> i).toArray(), nums);}return;}for (int i = start; i >= 0; i--) {if (i < start - 1 && nums[i] == nums[i + 1] && used[i + 1] == 0) continue;path.addLast(i);used[i] = 1;dfs2(nums, i - 1, path, used, target - nums[i]);path.removeLast();used[i] = 0;}}private static int[] getMoreBigger(int[] arr1, int[] arr2, int[] nums) {int i = 0;int size = arr1.length;while (i < size && arr1[i] == arr2[i]) {i++;}if (i >= size) return arr1;if ((i & 1) == 0) return nums[arr1[i]] > nums[arr2[i]] ? arr1 : arr2;else return nums[arr1[i]] > nums[arr2[i]] ? arr2 : arr1;}
}

推荐

如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/175233.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenMesh 网格曲率计算

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 借鉴之前点云主曲率计算的思路(Matlab 点云主曲率计算),这里基于网格顶点中每个邻近顶点的法向量来计算出点云中每个顶点的主曲率值。 二、实现代码

Spring Boot Admin(SBA)核心流程-注册篇

SBA是什么 首先我们简单了解一下Spring Boot Admin&#xff08;SBA&#xff09;&#xff0c;以下统一简称SBA是什么。借用官网的描述&#xff1a; SBA 是 codecentric 公司开发的一款开源社区项目&#xff0c;目标是让用户更方便的管理以及监控 Spring Boot 应用。 应用可以…

011 OpenCV warpAffine

目录 一、环境 二、warpAffine原理 三、完整代码 一、环境 本文使用环境为&#xff1a; Windows10Python 3.9.17opencv-python 4.8.0.74 二、warpAffine原理 warpAffine是OpenCV库中的一个函数&#xff0c;它用于执行二维仿射变换。这个函数接受一个输入图像和变换矩阵&…

二叉树的递归套路(1)

与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 是否平衡二叉树 &#x1f48e;总结 是否平衡二叉树 题目 给定一颗二叉树的头节点head&#xff0c;返回这颗二叉树是不是平衡二叉树 平衡二叉树就是这个树的所有子树和它自己&#xff0c;左右子树高度差不超过1 递归…

Rust语言入门教程(六) - 字符串类型

在Rust中&#xff0c; 字符串类型其实是一个比较复杂的话题。在Rust的标准库中&#xff0c;至少都提供了6种字符串类型&#xff0c;我们平常使用的最多的是其中的两种。这两种类型互相之间也有所关联&#xff1a; str&#xff1a; 字符串切片String 字符串 其中&#xff0c; 字…

Postman接口测试 —— 设置断言和集合运行

一、常见的5种断言方法 Postman是一款非常强大的API接口调式工具&#xff0c;它自带断言方法&#xff0c;不需要学习JavaScript脚本&#xff0c;非常方便。 &#xff08;1&#xff09;Status code&#xff1a;Code is 200(校验接口返回结果的状态码) &#xff08;2&#xff09…

python+feon有限元分析|求解实例

目录 1、feon框架结构 2. 支持的单元类型 3、实例 1、feon框架结构 包含三个包&#xff1a; sa&#xff1a;结构分析包 ffa&#xff1a;流体分析包 derivation&#xff1a;刚度矩阵包 2. 支持的单元类型 Spring1D11 - 一维弹簧单元 Spring2D11 - 二维弹簧单元 Spring…

Java进行计算两个时间间隔

在Java中&#xff0c;我们经常需要计算两个时间之间的间隔&#xff0c;比如计算某个任务的执行时间、计算两个事件发生的时间间隔等等。Java提供了一些类和方法来处理时间和日期相关的操作&#xff0c;本文将介绍如何使用Java来计算两个时间之间的间隔&#xff0c;并提供相应的…

再探Docker:从Docker基础到跨服务器部署

摘要&#xff1a; 这篇文章将从介绍Docker基础开始&#xff0c;逐步讲解如何创建镜像、使用Docker Compose编排容器、在Docker中更新部署环境&#xff0c;将更新后的环境打包为镜像并导出为tar包&#xff0c;最后在其他服务器上应用这个镜像。 1. Docker是什么 Docker是一种容…

MySQL运行在docker容器中会损失多少性能

前言 自从使用docker以来&#xff0c;就经常听说MySQL数据库最好别运行在容器中&#xff0c;性能会损失很多。一些之前没使用过容器的同事&#xff0c;对数据库运行在容器中也是忌讳莫深&#xff0c;甚至只要数据库跑在容器中出现性能问题时&#xff0c;首先就把问题推到容器上…

Java学习路线第一篇:Java基础(2)

这篇则分享Java学习路线第一part&#xff1a;Java基础&#xff08;2&#xff09; 从看到这篇内容开始&#xff0c;你就是被选定的天命骚年&#xff0c;将承担起学完Java基础的使命&#xff0c;本使命为单向契约&#xff0c;你可选择YES或者选择YES。 具体路线安排&#xff1a…

ubuntu 下载编译 opencv4.2.0并检验

如有帮助点赞收藏关注&#xff01; 如需转载&#xff0c;请注明出处&#xff01; ubuntu 的opencv4.2.0下载与编译 下载依赖开始编译安装配置OpenCV编译环境检验* 完成 下载 首先下载opencv源码网址&#xff1a; https://opencv.org/releases/page/3/ 下载成zip后&#xff0c;…

QMap key()和value(const Key key, const T defaultValue = T()) const第二个参数作用

value()函数介绍 返回与键key关联的值。 如果map不包含键为key的项&#xff0c;则该函数返回defaultValue。 如果没有指定defaultValue&#xff0c;该函数返回一个默认构造的值。 如果映射中有多个key项&#xff0c;则返回最近插入的项的值。 示例 定义自定义类型&#xff…

vue-历史模式部署

项目部署 本项目采用nginx进行部署&#xff0c;历史模式的部署需要服务端的配合&#xff0c;本次采用nginx进行配合。 1 配置 const basePath process.env.VUE_APP_BASE_PATH; module.exports {publicPath: basePath #静态资源的路径 /ecology/ }2 创建路由 const createR…

3D模型顶点颜色转纹理【SIMPLYGON】

在这篇博客中&#xff0c;我们将了解如何将顶点颜色烘焙到纹理中。 其用例是某些照片扫描资产&#xff0c;其中颜色数据保存到顶点颜色中。 我们将了解如何使用 remesher 和聚合器管道来完成此操作。 我们还将介绍如何为顶点颜色材质创建着色网络以及如何从模型后处理中删除顶点…

6.Spring源码解析-loadBeanDefinitions(String location)

这里resourceLoader其实就是ClassPathXmlApplicationContext 1.ClassPathXmlApplicationContext 在上文中图例就能看出来 获取资源组可能存在多个bean.xml 循环单独加载资源组 创建一个编码资源并解析 获取当前正在加载的资源发现是空 创建了一个字节输入流&#xff0c…

pytorch分布式训练

1 基本概念 rank&#xff1a;进程号&#xff0c;在多进程上下文中&#xff0c;我们通常假定rank 0是第一个进程或者主进程&#xff0c;其它进程分别具有1&#xff0c;2&#xff0c;3不同rank号&#xff0c;这样总共具有4个进程 node&#xff1a;物理节点&#xff0c;可以是一个…

Find My键盘|苹果Find My技术与键盘结合,智能防丢,全球定位

键盘是最常用也是最主要的输入设备&#xff0c;通过键盘可以将英文字母、汉字、数字、标点符号等输入到计算机中&#xff0c;从而向计算机发出命令、输入数据等。还有一些带有各种快捷键的键盘。随着时间的推移&#xff0c;渐渐的市场上也出现独立的具有各种快捷功能的产品单独…

单例模式-C++实现

目录 饿汉式懒汉式双检查锁&#xff0c;线程安全的版本什么是reorder&#xff1f;解决内存读写reorder不安全方法代码解释懒汉式的优缺点 单例模式是一种设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局的访问点来获取该实例。它常用于需要在整个应…

【软考】模块的内聚类型

目录 一、偶然内聚二、逻辑内聚三、时间内聚四、过程内聚五、通信内聚六、顺序内聚七、功能内聚 一、偶然内聚 1.最弱的内聚类型 2.又称巧合内聚&#xff0c;模块的各个成分之间毫无关系 二、逻辑内聚 1.逻辑上相关的功能被放在同一个模块中 2.如一个模块读取各种不同类型外设…