一组数中寻找加和最接近某个值的组合 JAVA实现

最近帮人做了一个题,就是在一组数中寻找一个子集合,使得这个子集合的数的加和最接近给定的某个值,此外,这些数的类型是浮点数。我第一想到是用01背包问题去解,但是感觉对于整型数好做,浮点数会难以控制精度。再次我给出三种做法,第一种是暴力做法,第二三中方法都是基于蒙特卡洛算法。

1、暴力法

这个方法的思路是使用深度优先遍历将给定数组的所有子集合给出,在代码中,我们按子集合内数字的个数依次给出,例如对于数组[1,2,3],我们先给出只有一个数字的子集合[1],[2],[3],再给出两个的和三个的。

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;public class baoli {public ArrayList<ArrayList<Double>> res = new ArrayList<>();/**** @param input 需要产生排列组合的数组* @param weishu 需要产生排列组合的位数* @param nowweishu 当前已经完成的位数* @param nowres 当前已经装入数组的数字* @param num_weishu 需要使用该位数之后的数字*/public void dfs(List<Double> input, int weishu, int nowweishu, ArrayList<Double> nowres, int num_weishu)//用来产生子集合{if(nowweishu == weishu){res.add((ArrayList<Double>) nowres.clone());return;}for(int i = num_weishu + 1;i<input.size();i++){nowres.add(input.get(i));dfs(input,weishu,nowweishu+1,nowres,i);nowres.remove(nowres.size()-1);}}public ArrayList<ArrayList<Double>> print(List<Double> input, int weishu) {res = new ArrayList<>();ArrayList<Double> nowres= new ArrayList<>();dfs(input,weishu,0,nowres,-1);return res;}public ArrayList<Double> sch_emuration(ArrayList<Double> nums,double target){double lapse = 10000;ArrayList<Double> res = new ArrayList<>();for (int i = 1;i<=nums.size();i++){ArrayList<ArrayList<Double>> ares = print(nums,i);for (int j = 0;j<ares.size();j++){double thissum = 0;for (int k = 0;k<ares.get(j).size();k++){thissum+=ares.get(j).get(k);}if (Math.abs(thissum - target)<lapse){res = (ArrayList<Double>) ares.get(j).clone();lapse = Math.abs(thissum - target);}}}return res;}public static void main(String args[]) {test t = new test();Random r = new Random();ArrayList<Double> nums =  new ArrayList<>();nums.add(8.05);nums.add(6.98);nums.add(6.19);nums.add(5.0);nums.add(22.96);nums.add(4.71);nums.add(4.74);nums.add(4.25);nums.add(6.34);nums.add(2.77);nums.add(7.31);nums.add(3.59);nums.add(19.55);ArrayList<Double> res = t.sch_emuration(nums,84.01);double sum = 0;for (int i=0;i<res.size();i++) {System.out.println(res.get(i));sum = sum + res.get(i);}System.out.println(sum);}
}

该方法的结果展示:

2、蒙特卡洛组合法

这个方法使用了随机的思想,每次随机得到一个子集合的数量,再依据这个数量随机选择数组中的数(可以使用HashMap避免重复选择)

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;public class mtkl {public ArrayList<Double> MC_combination(ArrayList<Double> nums,double target){ArrayList<Double> res = new ArrayList<>();double lapse = 10000;Random random = new Random();for (int i=0;i<1000000;i++){if(i%10000==0)System.out.println(i);int numsize = random.nextInt(nums.size()  + 1);ArrayList<Double> ares = new ArrayList<>();HashMap<Integer,Integer> map = new HashMap<>();double thissum = 0;for (int j=0 ;j<numsize;j++){int anumberindex = random.nextInt(nums.size());while (map.containsKey(anumberindex)){anumberindex = random.nextInt(nums.size());}map.put(anumberindex,1);ares.add(nums.get(anumberindex));thissum += nums.get(anumberindex);}if(Math.abs(thissum - target)<lapse){lapse = Math.abs(thissum - target);res = (ArrayList<Double>) ares.clone();}if(lapse<0.000001)break;}return res;}public static void main(String args[]) {Random r = new Random();ArrayList<Double> nums =  new ArrayList<>();nums.add(8.05);nums.add(6.98);nums.add(6.19);nums.add(5.0);nums.add(22.96);nums.add(4.71);nums.add(4.74);nums.add(4.25);nums.add(6.34);nums.add(2.77);nums.add(7.31);nums.add(3.59);nums.add(19.55);mtkl m = new mtkl();ArrayList<Double> res = m.MC_combination(nums,84.01);double sum = 0;for (int i=0;i<res.size();i++) {System.out.println(res.get(i));sum = sum + res.get(i);}System.out.println(sum);System.out.println(Math.abs(sum - 84.01));}
};

该方法的结果展示:

3、蒙特卡洛排列法

这个方法也是基于随机算法。该方法的思想是在每次计算前,都对数组进行一次打乱顺序,然后从头加和,直到加和的值大于给定目标值。这个方法没有前两个精度高,而且运算次数大于前两个,因此可以当一个思路。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;public class mtkl2 {public ArrayList<Double> MC_permutation(ArrayList<Double> nums,double target){ArrayList<Double> res = new ArrayList<>();for (int i=0;i<9000000;i++){double lapse = 10000;ArrayList<Double> newnum = (ArrayList<Double>) nums.clone();Collections.shuffle(newnum);double lastsum = 0;ArrayList<Double> alist = new ArrayList<>();for (int j = 0;j< newnum.size();j++){double thissum = lastsum + newnum.get(j);if(thissum>target){double ds1 = Math.abs(lastsum - target);double ds2 = Math.abs(thissum - target);double ds = Math.min(ds1,ds2);if(ds<lapse){lapse = ds;if(ds1<ds2){res = (ArrayList<Double>) alist.clone();}else{alist.add(newnum.get(j));res = (ArrayList<Double>) alist.clone();}break;}}alist.add(newnum.get(j));lastsum = thissum;}if(lapse<0.00001)break;}return res;}public static void main(String args[]) {ArrayList<Double> nums =  new ArrayList<>();nums.add(8.05);nums.add(6.98);nums.add(6.19);nums.add(5.0);nums.add(22.96);nums.add(4.71);nums.add(4.74);nums.add(4.25);nums.add(6.34);nums.add(2.77);nums.add(7.31);nums.add(3.59);nums.add(19.55);mtkl2 m = new mtkl2();ArrayList<Double> res = m.MC_permutation(nums,84.01);double sum = 0;for (int i=0;i<res.size();i++) {System.out.println(res.get(i));sum = sum + res.get(i);}System.out.println(sum);System.out.println(Math.abs(sum - 84.01));}
}

该方法的结果展示:

一组数中寻找加和最接近某个值的组合 JAVA实现相关推荐

  1. 在一组数中寻找加和最接近某个值的数组合

    在一组数中寻找加和最接近某个值的数组合 今天碰到个小问题,就是需要在一组数中,找到加和数最接近某个值的一系列数. 比如: [8.05, 6.98, 6.19, 5, 22.96,4.71,4.74,4 ...

  2. 【算法】从一组数中找出和为指定值的任意组合

    题目:给定的一组整数,给定一个值X,找出和为X的任意组合. 思路:将X视为重量x(kg)的物品,放在天平左侧,数组中的每个数字视为重量为y(kg)的砝码,砝码从大到小逐一放置,直到天平平衡,那么选择的 ...

  3. c语言中求大于的函数,c语言编写函数,求一组数中大于平均值的数的个数.

    C语言编写程序 给定一组数,求大于0,等于0,小于0的数据个数 #define N 10 main(){int num1=0,num2=0,num3=0,i;for(i=0;i 一道C语言题目:求一组 ...

  4. 6-7 求一组数中的最大值、最小值和平均值 (10 分)

    编写函数,求一组数中的最大值.最小值和平均值. 函数接口定义: float fun(int a[],int n,int *max,int *min); 其中 a.n.max 和 min 都是用户传入的 ...

  5. matlab产生一组均为一的矩阵,在matlab中如何从一组数中得到随机数组成一个n*n的矩阵...

    导航:网站首页 > 在matlab中如何从一组数中得到随机数组成一个n*n的矩阵 时间:2019-3-15 在matlab中如何从一组数中得到随机数组成一个n*n的矩阵 从1,2,3,4,5,6 ...

  6. python取出一组数中的奇偶数

    最近学习python,思考了如何取出一组数中的奇数和偶数. 面临这个问题,首先是得对数组进行一个一个的搜素判断.其次,我们知道偶数与2取模之后必为0,故采用模为0的思想来做: 代码如下: #案列1-- ...

  7. 数组系列—连续数中寻找缺失的数字

    连续数中寻找缺失的数字 通过散列表实现: public static void find(int[] array){Hashtable<Integer,Integer> hasht=new ...

  8. 查找一个数等于一组数中某些数相加的和

    实现需求: 查找一个数等于一组数中哪些数相加的和 例如: 从1, 2, 3, 4, 5, 6, 7 中找出和为5的数, 即2, 3 public class AccumulationUtil {pri ...

  9. 6-4 求一组数中的最大值、最小值和平均值

    6-4 求一组数中的最大值.最小值和平均值 编写函数,求一组数中的最大值.最小值和平均值. 函数接口定义: float fun(int a[],int n,int *max,int *min); 其中 ...

最新文章

  1. InnoDB体系结构
  2. 统计学习II.7 广义线性模型1 指数分布族
  3. Asp.Net Session学习总结
  4. VTK:图片之ImageLuminance
  5. 在vscode上运行linux代码,在linux上安装VSCode
  6. android 回归测试,android测试:monkey使用方法
  7. java静态类如何赋值_Java class对象说明 Java 静态变量声明和赋值说明
  8. java 线程锁概念_Java多线程——锁概念与锁优化
  9. C语言-指针的比较/指针加减
  10. JavaScript 作用域不完全指北
  11. 精度提升第一步:形状各异测区的像控点布设方案
  12. [android]亲自破解Flappy Bird(去广告+永生)
  13. 05-1_部署 master 节点
  14. 【Java 判断素数的几个方法】简单理解
  15. oracle 联合查询去重,oracle两张表关联查询
  16. EINT DINT ERTM DRTM EALLOW EDIS ESTOP0的理解
  17. ch4_3_5利用radon函数和iradon函数构造一个简单图像的投影并重建图像.m
  18. 11. 深度学习实践:实践方法论
  19. 图解Linux网络包接收过程
  20. Java大牛呕心沥血经历——技术面试与HR谈薪资技巧...

热门文章

  1. mt6762芯片资料,MTK6762最新资料
  2. 创业者必看:合伙人股权的进入机制与退出机制
  3. 2023全新SF授权系统源码 V3.7全开源无加密版本,亲测可用
  4. 在浏览器访问不到在阿里云购买服务器的公网ip的解决历程
  5. 关于推荐系统的详细介绍
  6. 如何建站?如何使用宝塔?宝塔是什么?
  7. 强大的MySQL 官方压测神器,简单、易用
  8. 关于固定表头的一种方式
  9. jquery chosen插件使用及select常用方法
  10. 聚合数据火车票订票接口完成火车票订票流程(PHP)