今天没事,撸一道算法题

  题目要求:

  给出一个升序排序的可能重复值的数字数组和一个目标值其中目标值大于数组中最小数,求数组中数字组合(可多值组合)相加最接近目标数的组合(可能多个)不考虑空间复杂度,效率最优的算法;样例:数组为[3,4,8,6],目标值为9,最接近组合为[8]和[4,6];

  这道题我的解题思路是:

   1.先得到数组的全部不重复不为空的子集

   2.将子集的和作为key,子集的元素作为value存进map

   3.将子集的和与给定值相减,然后取绝对值,最小的就是题目要的结果

  
  比如:集合是arr={3,4,8},目标值为9
  
  集合的所有不为空的子集为{3},{4},{8},{3,4},{3,8},{4,8},{3,4,8}
  
  六个集合的和分别为3,4,8,7,11,12,15,将这六个数作为key存进map中,value是对应的元素集合,然后把每一个数与目标值(9)相减并取绝对值。
    
  可得到结果为|3-9|=6,|4-9|=5,|8-9=|1,|7-9|=2,|11-9|=3,|15-9|=6,可以看到|8-9|=1是最小的,也就是输出{8}这个子集符合题意。

  不多比比,下面是求集合子集的代码

 public static List<List<Integer>> getArr(List<Integer> list) {if(list.size()>0){//当数组长度大于0时才进行子集获取List<List<Integer>> result = new ArrayList<>();long n = (long) Math.pow(2, list.size());//集合的子集数量  2的数组长度次方List<Integer> temp;for (long l = 0L; l < n; l++) {//遍历出的子集的个数temp = new ArrayList<>();for (int i = 0; i < list.size(); i++) {if ((l >>> i & 1) == 1) {temp.add(list.get(i));//用一个List<Integer>来装每个子集中的元素}}if (!temp.isEmpty()) result.add(temp);//当获取到的子集不为空时就放入返回结果中}return result;}return null;}

   有兴趣可以复制到idea里跑一下

  这部分代码的原理如下:

000 无符号右移0位 与1位与运算后 000 !=1
000 无符号右移1位 与1位与运算后 000 !=1
000 无符号右移2位 与1位与运算后 000 !=1001 无符号右移0位 与1位与运算后 001   =1 获得下标为0的元素 第一个子集
001无符号右移1位 与1位与运算后 000  !=1
001无符号右移2位 与1位与运算后 000  !=1010 无符号右移0位 与1位与运算后 010 !=1
010 无符号右移1位 与1位与运算后 001   =1  获得下标1的元素 第二个子集
010 无符号右移2位 与1位与运算后 000 !=1011 无符号右移0位 与1位与运算后 001   =1
011 无符号右移1位 与1位与运算后 001   =1 获取下标为0,1的元素 第三个子集
011 无符号右移2位 与1位与运算后 000 !=1100 无符号右移0位 与1位与运算后 000 !=1
100 无符号右移1位 与1位与运算后 000 !=1
100 无符号右移2位 与1位与运算后 001  =1 获取下标为2的元素 第四个子集101 无符号右移0位 与1位与运算后 001   =1
101 无符号右移1位 与1位与运算后 000 !=1 获取下标为0,2的元素 第五个子集
101 无符号右移2位 与1位与运算后 001   =1110 无符号右移0位 与1位与运算后 000 !=1
110 无符号右移1位 与1位与运算后 001  =1  获取下标为1,2的元素第六个子集
110 无符号右移2位 与1位与运算后 000  =1111 无符号右移0位 与1位与运算后 001  =1
111 无符号右移1位 与1位与运算后 001  =1  获取下标为0,1,2的元素 第七个子集
111 无符号右移2位 与1位与运算后 001  =1输入:
123
输出:
1
2
12
3
13
23
123

  得到所有子集后,求和放入map,将子集的和与目标值相减取最小的绝对值对应的子集并输出,代码如下:

   public static List<List<Integer>> back(List<List<Integer>> list,Integer x){List<List<Integer>> lists = new ArrayList<>();ArrayList<Integer> objects = new ArrayList<Integer>();Integer sum=new Integer(0);for (int i = 0; i < list.size(); i++) {List<Integer> integers = list.get(i);for (int i1 = 0; i1 < integers.size(); i1++) {sum+=integers.get(i1);objects.add(Math.abs(sum-x));}sum=0;}Integer min = Collections.min(objects);for (int i = 0; i < list.size(); i++) {List<Integer> integers = list.get(i);for (int i1 = 0; i1 < integers.size(); i1++) {sum+=integers.get(i1);}if(min==Math.abs(sum-x)){lists.add(integers);}sum=0;}return lists;}

  最后测试一下:

     public static void main(String[] args) {List<Integer> integers = new ArrayList<>();integers.add(new Integer(6));integers.add(new Integer(26));integers.add(new Integer(37));integers.add(new Integer(50));integers.add(new Integer(50));integers.add(new Integer(31));integers.add(new Integer(16));List<List<Integer>> arr = getArr(integers);List<List<Integer>> back = back(arr, 100);for (int i = 0; i < back.size(); i++) {List<Integer> l1 = back.get(i);for (int i1 = 0; i1 < l1.size(); i1++) {System.out.print(l1.get(i1)+"  ");}System.out.println();}}输出:50  50  6  26  37  31  Process finished with exit code 06+26+37+31=100

完事

(算法)求数组中数字组合(可多值组合)相加最接近目标数的组合(可能多个)相关推荐

  1. java数组排列组合_java算法题--递归求数组中数字排列组合问题

    java算法题–递归求数组中数字排列组合问题 题目:有一个数组{1,2,3},输出数组中数字的所有可能组合: 比如:123.132.213- 解题思路 通过递归不停的交换数组中的两个数(当然,肯定是有 ...

  2. leetcode算法题--数组中数字出现的次数 II

    原题链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/ int singleNumb ...

  3. leetcode算法题--数组中数字出现的次数

    原题链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/ vector<int> ...

  4. python两两组合_求数组中两两相加等于20的组合(Python实现)

    题目 求数组中两两相加等于20的组合. 例:给定一个数组[1, 7, 17, 2, 6, 3, 14],这个数组中满足条件的有两对:17+3=20, 6+14=20. 解析 分为两个步骤: 先采用堆排 ...

  5. 求数组中k个数的所有组合

    /*** 求数组中 k个元素序列 的所有组合* @param start* @param array* @param length* @param k* @param list* @param use ...

  6. Java学习——已知有六个数字1,2,3,4,5,6 在要求将这六个数字中所有的组合存放到数组中 (1)必须是6位数 (2)每个位置上的数不能重复

    这个题目,最笨的方法就是循环套循环 1,让每一层都输出1到6的数字,6层循环,就能得到6个1~6的数字 2,然后再给他们单行输出,就能拿到类似于123456 456123......的数字 3,再让他 ...

  7. java求数组中满足给定和的数对_关于数组的几道面试题 - zdd - 博客园

    2011年2月15日更新,加入找出绝对值最小的元素一题 数组是最基本的数据结构,关于数组的面试题也屡见不鲜,本文罗列了一些常见的面试题,仅供参考,如果您有更好的题目或者想法,欢迎留言讨论.目前有以下1 ...

  8. C++求数组中的逆序对

    C++求数组中的逆序对. 如果在数组中的两个数字如果前面的一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数 #include<iostream> ...

  9. 动态规划系列---求数组中两个元素差的最大值

    题目 求数组中两个元素差的最大值(后面的元素减去前面的元素):对应实际生活中的股票买卖,找出一只股票走势里面可能的最大收益: 思路 类似于求数组连续和的最大值:  保存最大差值和最小值,遍历数组,如果 ...

最新文章

  1. Golang 本地帮助文档
  2. 《图解CSS3:核心技术与案例实战》——1.1节什么是CSS3
  3. 第一轮复习完毕,kmp走起
  4. nimm博弈必胜方可操作种数HDU - 1850
  5. 用shell写的ftp工具
  6. Python3 高级用法
  7. Java常用设计模式的实例学习系列-绪论
  8. 灰色系统理论(Matlab实现)
  9. 泛微协同商务系统办公自动化解决方案
  10. ReportMachine如何导出PDF文档?
  11. 2019年中国公有云厂商发展状况白皮书
  12. 往虚拟机中导入虚拟硬盘出现错误 返回 代码: E_INVALIDARG (0x80070057)的解决方法
  13. 小熊派BearPi-HM nano开发板 -- MobaXterm使用详情、VScode连接编译主机、小熊派源码获取及烧录
  14. 阿里云认证是什么?报考要什么条件?
  15. 【无代码体验】用鲸智搭替换Excel表管理数据
  16. [4G5G专题-91]:流程 - 4G LTE 终端移动性管理总体概述
  17. 新手看Mockplus2.3
  18. 项目训练营模块学习---Oled屏幕
  19. 企业微信与个人微信实现消息互通,用企业微信连接10亿客户
  20. 联想笔记本如何关闭Fn功能键

热门文章

  1. 助创cms二手车众筹系统:汽车众筹平台绝佳时机来临!
  2. 度量空间(metric space)
  3. Java中的逻辑控制与方法(上)
  4. c语言 程序竞赛题,C语言程序设计竞赛题目(学生使用).doc
  5. 苍溪师范94级计算机与文秘专业就业前景,2019文秘专业就业前景和就业方向分析...
  6. 海藻酸钠-PEG-N-羟基琥珀酰亚胺 NHS-PEG-alginate
  7. 【三角】【棱形】【等等】
  8. 大数据之Hive函数及案例
  9. 车载网络测试 - UDS诊断篇 - 诊断RID/IOID($2F/$31)
  10. 笔记本插入麦克风被识别成耳机怎么办