问题描述:
从一个文件中读取 整型数组数据,并通过算法 输出该数据 组合和的情况。
package lc.mqproducer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ConvenienceStoreHomeWorkDemo {
public static void main(String[] args) {
//需要查找的文件全路径
String fileUrl = "D:\\IdeaWorkSpace\\lcmyself\\microserviceparent2020\\microservice-lcintegratedproject\\src\\main\\java\\lc\\mqproducer\\nums.txt";
//目标值
int target = 4;
doConvenienceStoreHomeWork(fileUrl, target);
}
private static void doConvenienceStoreHomeWork(String fileUrl, int target) {
try {
//1.查找文件 并最终转化为最终解析完的整型数组
int[] candidates = findFileAndSolve2IntegArr(fileUrl);
//2.解决leetcode 39组合总和问题 dp方式
List<List<Integer>> list = combinationSum2(candidates, target);
System.out.println("最终结果:" + list);
} catch (Exception e) {
throw e;
}
}
private static int[] findFileAndSolve2IntegArr(String fileUrl) throws RuntimeException {
FileInputStream fis = null;
int[] array = null;
try {
File f = new File(fileUrl);
if (f.exists() && f.isFile()) {
if (f.length() > 1024) { //校验文件尺寸是否超过1M
throw new RuntimeException("文件过大 已超过1M,请选择其他文件");
}
} else {
throw new RuntimeException("文件或目录不存在或不是一个标准文件");
}
fis = new FileInputStream(f);
int fileCapacity = fis.available();
byte[] buf = new byte[fileCapacity];//定义一个刚刚好的缓冲区,不用再循环了。
fis.read(buf);
String transferFileData2Str = new String(buf);//解析转换文件内容
//解析内容为整型数组并校验文件内容格式, 若存在非整型数据 lambda表达式流异常会被catch
array = Arrays.asList(transferFileData2Str.split(",")).stream().mapToInt(Integer::parseInt).toArray();
System.out.println("文件内容解析后的整型数组为array:" + Arrays.toString(array));
} catch (NumberFormatException e) {
throw new RuntimeException("文件中包含非整数内容,请重新修改文件内容");
} catch (FileNotFoundException e) {
throw new RuntimeException("文件未被找到");
} catch (IOException e) {
throw new RuntimeException("文件流解析存在异常");
} catch (Exception e) {
throw new RuntimeException("查找文件 系统内部其他异常");
} finally {
try {
fis.close();
} catch (IOException e) {
throw new RuntimeException("IO流关闭异常");
}
}
return array;
}
public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
try {
if (candidates == null) {
return new ArrayList<>();
}
Arrays.sort(candidates);//对数据排序
return combinationSum(candidates, target, 0);
} catch (Exception e) {//兜底 leetcode 39算法内部异常
throw new RuntimeException("系统内部 leetcode 39算法异常");
}
}
/**
* leetcode 39算法 动态规划思路
* 设原数组为aa,返回值为f(n)f(n),那么对于其中第i项来说:
* 如果a[i] = targeta[i]=target,那么它一个数就成为一个组合;
* 如果a[i] < targeta[i]<target,那么a[i]a[i]与f(n - a[i])f(n−a[i])中所有List都构成满足条件的组合;
* 如果a[i] > targeta[i]>target,无解。
* 作者:LittleFogCat
* 链接:https://leetcode-cn.com/problems/combination-sum/solution/dong-tai-gui-hua-39-zu-he-zong-he-by-lit-ko8e/
* 来源:力扣(LeetCode)
* 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
public static List<List<Integer>> combinationSum(int[] candidates, int target, int start) {
List<List<Integer>> r = new ArrayList<>();
for (int i = start; i < candidates.length; i++) {
int num = candidates[i];
if (target == num) {
List<Integer> list = new ArrayList<>();
list.add(num);
r.add(list);
}
if (target > num) {
int nTarget = target - num;
List<List<Integer>> nR = combinationSum(candidates, nTarget, i + 1);
for (List<Integer> list : nR) {
list.add(num);
}
r.addAll(nR);
}
while (i + 1 < candidates.length && candidates[i + 1] == candidates[i]) i++;
}
return r;
}
}