• 求和算法


    要求

    给定一个数组,一个目标值,算出所有和等于目标值的组合,组合中会出现重复值,且每个重复值只能在每个组合出现一次。

    包含小数。

    import java.util.*;
    
    public class Match {
    
        public static void main(String[] args) {
            Double[] nums = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 5.5, 0.5, 0.5, 0.4};
            List<Double> nlist = Arrays.asList(nums);
            Double target = 8.0;
    
            List<List<Double>> result = sum(nlist, target, null);
            for (List<Double> doubles : result) {
                System.out.println(Arrays.toString(new List[]{doubles}));
            }
        }
    
    
        public static List<List<Double>> sum(List<Double> nums, Double target, List<List<Double>> currentMatch) {
            int len = nums.size();
            if (Objects.isNull(currentMatch)) currentMatch = new ArrayList<>();
    
            for (int i = 0; i < len; i++) {
                if (target < nums.get(i)) continue;
                for (int j = i + 1; j < nums.size(); j++) {
                    if (target < nums.get(j)) continue;
                    if (nums.get(i) + nums.get(j) == target) {
                        currentMatch.add(List.of(new Double[]{nums.get(i), nums.get(j)}));
                    } else if ((nums.get(i) + nums.get(j)) < target) {
                        List<Double> p1 = new ArrayList<>();
                        p1.add(nums.get(i));
                        p1.add(nums.get(j));
                        List<Double> tempNums = new ArrayList<>(nums);
                        getMatch(p1, tempNums, j + 1, target, currentMatch, null);
                    }
                }
            }
            return currentMatch;
        }
    
    
        public static void getMatch(List<Double> p1, List<Double> nums, int i, Double target, List<List<Double>> currentMatch, List<Integer> exclude) {
            if (Objects.isNull(exclude)) exclude = new ArrayList<>();
            int len = nums.size();
            for (; i < len; i++) {
                int finalI = i;
                if (exclude.stream().anyMatch((e)-> e == finalI))continue;
                if ((getSum(p1) + nums.get(i)) == target) {
                    p1.add(nums.get(i));
                    currentMatch.add(p1);
                    exclude.clear();
                } else if ((getSum(p1) + nums.get(i)) < target) {
                    p1.add(nums.get(i));
                    exclude.add(i);
                    getMatch(p1, nums, i + 1, target, currentMatch, exclude);
                }
            }
        }
    
    
        static Double getSum(List<Double> r) {
            if (r.isEmpty()) {
                return 0.0;
            } else {
                return r.stream().mapToDouble(Double::doubleValue).sum();
            }
        }
    }
    

      

    大概思路是,O(n^2) 循环内先看前后两数的和是否为目标值,如果这两个数相加小于目标值,那么进入递归算出组合。

    将已选出的组合数字在递归循环中排除。

    if (exclude.stream().anyMatch((e)-> e == finalI))continue;

    可以确保值只被使用一次。

    优化空间还是有的,只不过我懒得看了。

  • 相关阅读:
    Oracle数据库用户密码设为无限期
    CentOS 7设置网卡开机自动启用
    求凹多边形的视觉中心,不是质心、重心
    autocad数据交换格式dxf读取
    gis资源站
    geotools的空间索引使用——R树和四叉树
    JTS的泰森多边形
    Geotools的delaunry三角剖分
    geotools的最短路径实现
    java多线程
  • 原文地址:https://www.cnblogs.com/yangchaojie/p/16284718.html
Copyright © 2020-2023  润新知