|
@@ -0,0 +1,104 @@
|
|
|
|
|
+package org.springblade.manager.utils;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @author LHB
|
|
|
|
|
+ * 字符串拆分
|
|
|
|
|
+ */
|
|
|
|
|
+public class NumberStringSubtraction {
|
|
|
|
|
+
|
|
|
|
|
+ public static List<Integer> calculateDifference(String a, String b) {
|
|
|
|
|
+ // 分割字符串为数字列表
|
|
|
|
|
+ List<Integer> aNumbers = parseNumbers(a);
|
|
|
|
|
+ List<Integer> bNumbers = parseNumbers(b);
|
|
|
|
|
+
|
|
|
|
|
+ List<Integer> result = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ // 情况1:数字数量一致,一一对应计算
|
|
|
|
|
+ if (aNumbers.size() == bNumbers.size()) {
|
|
|
|
|
+ for (int i = 0; i < aNumbers.size(); i++) {
|
|
|
|
|
+ result.add(aNumbers.get(i) - bNumbers.get(i));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 情况2:数字数量不一致,b数字可重复使用
|
|
|
|
|
+ else {
|
|
|
|
|
+ // 对b数字列表排序,便于查找
|
|
|
|
|
+ List<Integer> sortedBNumbers = new ArrayList<>(bNumbers);
|
|
|
|
|
+ Collections.sort(sortedBNumbers);
|
|
|
|
|
+
|
|
|
|
|
+ for (int aNum : aNumbers) {
|
|
|
|
|
+ // 在b数字中找到最接近且小于等于aNum的数字
|
|
|
|
|
+ int bestB = findClosestWithPreference(aNum, sortedBNumbers);
|
|
|
|
|
+ result.add(aNum - bestB);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static int findClosestWithPreference(int aNum, List<Integer> sortedBNumbers) {
|
|
|
|
|
+ // 如果b列表为空,返回0
|
|
|
|
|
+ if (sortedBNumbers.isEmpty()) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 找到所有与aNum差值最小的数字
|
|
|
|
|
+ List<Integer> closestNumbers = new ArrayList<>();
|
|
|
|
|
+ int minDiff = Integer.MAX_VALUE;
|
|
|
|
|
+
|
|
|
|
|
+ for (int bNum : sortedBNumbers) {
|
|
|
|
|
+ int diff = Math.abs(aNum - bNum);
|
|
|
|
|
+ if (diff < minDiff) {
|
|
|
|
|
+ minDiff = diff;
|
|
|
|
|
+ closestNumbers.clear();
|
|
|
|
|
+ closestNumbers.add(bNum);
|
|
|
|
|
+ } else if (diff == minDiff) {
|
|
|
|
|
+ closestNumbers.add(bNum);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果只有一个最接近的数字,直接返回
|
|
|
|
|
+ if (closestNumbers.size() == 1) {
|
|
|
|
|
+ return closestNumbers.get(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有多个相同接近的数字,优先选择小于aNum的
|
|
|
|
|
+ List<Integer> greaterThanA = new ArrayList<>();
|
|
|
|
|
+ for (int num : closestNumbers) {
|
|
|
|
|
+ if (num < aNum) {
|
|
|
|
|
+ greaterThanA.add(num);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有大于aNum的数字,返回其中最小的
|
|
|
|
|
+ if (!greaterThanA.isEmpty()) {
|
|
|
|
|
+ Collections.sort(greaterThanA);
|
|
|
|
|
+ return greaterThanA.get(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有大于aNum的数字,返回最大的那个(最接近但小于等于aNum的)
|
|
|
|
|
+ Collections.sort(closestNumbers);
|
|
|
|
|
+ return closestNumbers.get(closestNumbers.size() - 1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static List<Integer> parseNumbers(String str) {
|
|
|
|
|
+ List<Integer> numbers = new ArrayList<>();
|
|
|
|
|
+ if (str == null || str.trim().isEmpty()) {
|
|
|
|
|
+ return numbers;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 支持多种分隔符:/ , 空格 \
|
|
|
|
|
+ String[] parts = str.split("[\\\\/,,、\\s]+");
|
|
|
|
|
+ for (String part : parts) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ numbers.add(Integer.parseInt(part.trim()));
|
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
|
+ // 忽略非数字部分
|
|
|
|
|
+ System.err.println("警告: 忽略非数字部分: " + part);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return numbers;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|