一组数中寻找加和最接近某个值的组合 JAVA实现
一组数中寻找加和最接近某个值的组合 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实现相关推荐
- 在一组数中寻找加和最接近某个值的数组合
在一组数中寻找加和最接近某个值的数组合 今天碰到个小问题,就是需要在一组数中,找到加和数最接近某个值的一系列数. 比如: [8.05, 6.98, 6.19, 5, 22.96,4.71,4.74,4 ...
- 【算法】从一组数中找出和为指定值的任意组合
题目:给定的一组整数,给定一个值X,找出和为X的任意组合. 思路:将X视为重量x(kg)的物品,放在天平左侧,数组中的每个数字视为重量为y(kg)的砝码,砝码从大到小逐一放置,直到天平平衡,那么选择的 ...
- c语言中求大于的函数,c语言编写函数,求一组数中大于平均值的数的个数.
C语言编写程序 给定一组数,求大于0,等于0,小于0的数据个数 #define N 10 main(){int num1=0,num2=0,num3=0,i;for(i=0;i 一道C语言题目:求一组 ...
- 6-7 求一组数中的最大值、最小值和平均值 (10 分)
编写函数,求一组数中的最大值.最小值和平均值. 函数接口定义: float fun(int a[],int n,int *max,int *min); 其中 a.n.max 和 min 都是用户传入的 ...
- matlab产生一组均为一的矩阵,在matlab中如何从一组数中得到随机数组成一个n*n的矩阵...
导航:网站首页 > 在matlab中如何从一组数中得到随机数组成一个n*n的矩阵 时间:2019-3-15 在matlab中如何从一组数中得到随机数组成一个n*n的矩阵 从1,2,3,4,5,6 ...
- python取出一组数中的奇偶数
最近学习python,思考了如何取出一组数中的奇数和偶数. 面临这个问题,首先是得对数组进行一个一个的搜素判断.其次,我们知道偶数与2取模之后必为0,故采用模为0的思想来做: 代码如下: #案列1-- ...
- 数组系列—连续数中寻找缺失的数字
连续数中寻找缺失的数字 通过散列表实现: public static void find(int[] array){Hashtable<Integer,Integer> hasht=new ...
- 查找一个数等于一组数中某些数相加的和
实现需求: 查找一个数等于一组数中哪些数相加的和 例如: 从1, 2, 3, 4, 5, 6, 7 中找出和为5的数, 即2, 3 public class AccumulationUtil {pri ...
- 6-4 求一组数中的最大值、最小值和平均值
6-4 求一组数中的最大值.最小值和平均值 编写函数,求一组数中的最大值.最小值和平均值. 函数接口定义: float fun(int a[],int n,int *max,int *min); 其中 ...
最新文章
- InnoDB体系结构
- 统计学习II.7 广义线性模型1 指数分布族
- Asp.Net Session学习总结
- VTK:图片之ImageLuminance
- 在vscode上运行linux代码,在linux上安装VSCode
- android 回归测试,android测试:monkey使用方法
- java静态类如何赋值_Java class对象说明 Java 静态变量声明和赋值说明
- java 线程锁概念_Java多线程——锁概念与锁优化
- C语言-指针的比较/指针加减
- JavaScript 作用域不完全指北
- 精度提升第一步:形状各异测区的像控点布设方案
- [android]亲自破解Flappy Bird(去广告+永生)
- 05-1_部署 master 节点
- 【Java 判断素数的几个方法】简单理解
- oracle 联合查询去重,oracle两张表关联查询
- EINT DINT ERTM DRTM EALLOW EDIS ESTOP0的理解
- ch4_3_5利用radon函数和iradon函数构造一个简单图像的投影并重建图像.m
- 11. 深度学习实践:实践方法论
- 图解Linux网络包接收过程
- Java大牛呕心沥血经历——技术面试与HR谈薪资技巧...