给定顺序的数字间增加加减乘除得到的可能值算法

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

 

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