skyouc
1 天以前 45a230e870b26b51d3006273a36df78203521253
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
public class CombinationFinder {
 
    public List<Integer> findCombination(double[] nums, double target) {
        // 处理等值情况
        List<Integer> equal = findEqual(nums, target);
        if (equal != null && !equal.isEmpty()) {
            return equal;
        }
 
        // 处理大于的情况
        List<Integer> greater = findGreater(nums, target);
        if (greater != null && !greater.isEmpty()) {
            return greater;
        }
 
        // 处理小于的情况
        List<Integer> less = findLess(nums, target);
        return less != null ? less : new ArrayList<>(); // 确保不返回null
    }
 
    private List<Integer> findEqual(double[] nums, double target) {
        int n = nums.length;
        double[] dp = new double[(int) (target * 100 + 1)]; // 放大100倍处理精度问题
        Arrays.fill(dp, Double.MAX_VALUE);
        dp[0] = 0;
        int[] prev = new int[(int) (target * 100 + 1)];
        Arrays.fill(prev, -1);
 
        for (int j = 0; j < n; j++) {
            int num = (int) (nums[j] * 100); // 放大100倍处理精度问题
            for (int i = (int) (target * 100); i >= num; i--) {
                if (dp[i - num] != Double.MAX_VALUE && dp[i - num] + 1 < dp[i]) {
                    dp[i] = dp[i - num] + 1;
                    prev[i] = j;
                }
            }
        }
 
        if (dp[(int) (target * 100)] == Double.MAX_VALUE) {
            return null;
        }
 
        List<Integer> indices = new ArrayList<>();
        int current = (int) (target * 100);
        while (current > 0) {
            int j = prev[current];
            if (j == -1) return null;
            indices.add(j);
            current -= (int) (nums[j] * 100);
        }
 
        return indices;
    }
 
    private List<Integer> findGreater(double[] nums, double target) {
        List<double[]> sorted = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            sorted.add(new double[]{nums[i], i});
        }
        sorted.sort((a, b) -> Double.compare(b[0], a[0]));
 
        double sum = 0;
        List<Integer> indices = new ArrayList<>();
        for (double[] pair : sorted) {
            sum += pair[0];
            indices.add((int) pair[1]);
            if (sum > target) {
                return indices;
            }
        }
 
        return null;
    }
 
    private List<Integer> findLess(double[] nums, double target) {
        int n = nums.length;
        List<Integer> bestIndices = new ArrayList<>();
        double[] maxSum = {-1.0};
        for (int k = 1; k <= n; k++) {
            List<Integer> currentIndices = new ArrayList<>();
            double[] currentMax = {-1.0};
            backtrack(nums, target, 0, k, 0.0, 0, currentIndices, currentMax, new ArrayList<>());
            if (currentMax[0] != -1.0) {
                if (currentMax[0] > maxSum[0] || (currentMax[0] == maxSum[0] && currentIndices.size() < bestIndices.size())) {
                    maxSum[0] = currentMax[0];
                    bestIndices = new ArrayList<>(currentIndices);
                }
            }
        }
 
        return bestIndices.isEmpty() ? null : bestIndices;
    }
 
    private void backtrack(double[] nums, double target, int start, int k, double currentSum, int count, List<Integer> currentIndices, double[] currentMax, List<Integer> path) {
        if (count == k) {
            if (currentSum <= target && currentSum > currentMax[0]) {
                currentMax[0] = currentSum;
                currentIndices.clear();
                currentIndices.addAll(path);
            }
            return;
        }
 
        for (int i = start; i < nums.length; i++) {
            if (currentSum + nums[i] > target) continue;
            path.add(i);
            backtrack(nums, target, i + 1, k, currentSum + nums[i], count + 1, currentIndices, currentMax, path);
            path.remove(path.size() - 1);
        }
    }
 
    public static void main(String[] args) {
        CombinationFinder finder = new CombinationFinder();
        double[] nums = {3.0, 1.0, 4.0, 2.0};
        double target = 0.1;
        List<Integer> result = finder.findCombination(nums, target);
        System.out.println("最优组合的索引: " + result); // 例如,等值组合可能为索引2(4.0)和3(1.0)
    }
}