給定順序的數字間增加加減乘除得到的可能值算法

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章