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空間有發表本文,略有修改。