package util;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
package com.lin;
import java.util.*;
/**
* ${DESCRIPTION}
*
* @author lin
* @create 2019-07-29 15:35
**/
public class MathTest {
public static void main(String[] args) {
List<Integer> listnum = new ArrayList<Integer>() {
{
add(5);
add(1);
add(1);
add(0);
add(2);
}
};
List<Integer> finalReslut = new MathTest().method(listnum);
Collections.sort(finalReslut);
System.out.println(finalReslut);
}
private List<Integer> method(List<Integer> listnum) {
List<Integer> listReslut = new ArrayList<>();
Set<Integer> set = new HashSet<>();
List<Integer> signList = new ArrayList<>();
for (int k = 0; k < listnum.size() - 1; k++) {
signList.add(0);
}
for (int i = 0; i < Math.pow(4, listnum.size() - 1); i++) {
Integer m = i;
Integer j = 0;
while (m > 0) {
signList.set(signList.size() - 1 - j, m % 4);
j++;
m = m / 4;
}
set.add(myMethod(signList, listnum));
}
listReslut.addAll(set);
return listReslut;
}
private int myMethod(List<Integer> list, List<Integer> listnum) {
List<Integer> listSignCopy = new ArrayList<Integer>();
List<Integer> listNumCopy = new ArrayList<Integer>();
listSignCopy.addAll(list);
listNumCopy.addAll(listnum);
while (listSignCopy.contains(2) || listSignCopy.contains(3)) {
//合并乘除,一次只去除一个乘号或者除号
for (int m = 0; m < listSignCopy.size(); m++) {
if (listSignCopy.get(m) == 2 || listSignCopy.get(m) == 3) {
try {//如果被除数是0可能会报错,直接跳过
listNumCopy.set(m, listSignCopy.get(m) == 2 ? listNumCopy.get(m) * listNumCopy.get(m + 1) : listNumCopy.get(m) / listNumCopy.get(m + 1));
} catch (Exception e) {
}
listNumCopy.remove(m + 1);
listSignCopy.remove(m);
break;
}
}
}
//合并加减
while ( listSignCopy.size() > 0) {
listNumCopy.set(0, listSignCopy.get(0) == 0 ? listNumCopy.get(0) + listNumCopy.get(1) : listNumCopy.get(0) - listNumCopy.get(1));
listNumCopy.remove(1);
listSignCopy.remove(0);
}
return listNumCopy.get(0);
}
}
更新下格式
主要思路当然是遍历所有情况运算得出值存入set。然后拷贝到list排序。数字集合listNum,运算符号集合signList
红色myMethod是运算逻辑这里采用的是 先乘除后加减的原则 合并2个数并去除运算符号, 比如 2*5+9-5经过一次合并后10+9-5。直到合并至没有运算符号即为该次的最终值。
蓝色method构建所有运算符号的排列组合,不知道别人的排列组合用的什么算法实现,我这里的思路是:首先运算符号集合signList中0 1 2 3分别代表加简乘除运算法则
且长度总是数字集listNum.size()-1;初始化signList默认为0,我们只需遍历出0 1 2 3的排列组合,这里想到了四进制算法。
对4辗转相除取余数的值倒序为该次排列(其实也不用倒序,反正要求出所有排列,不顾倒序确实更好操作,因为正序还要判断该次排列的长度),然后将改次排列存入signList调用method即遍历出所有可能值。
本来是csdn上别人的一个提问,然后捣腾出这个通用算法,解决了我多年对于 遍历循环次数为变量的循环 的疑问,那便是利用进制转换巧妙解决,只需将method中的 4 换成变量即可,同时排列组合的问题也可以用该方法,感觉开启了新世界的大门-_,-
本人于qq空间有发表本文,略有修改。