24点算法


一、算法介绍

根据华为机试题完善的算法,此次算法输入:4个数字,输出:所有结果为24的计算公式
华为机试题
华为机试题

二、思路及代码

1.思路

暴力解法,穷举所有组合产生的运算结果。
用到了组合思想

  1. 从长度为4的数组arr4中取出2个数,共计6种组合数C24
  2. 计算每组组合数的6种结果:a+b;a-b;b-a;a*b;若b!=0,a/b;若a!=0,b/a
  3. 将这6种计算结果分别替换原数组参与计算的两个数。
  4. 返回 36X3的二维数组arr3

第一层循环arr3: 选出每个长度为3的数组元素的组合数,并计算每组组合数的6种结果,将这6种计算结果分别替换原数组参与计算的两个数。每次循环返回一个18X2的二维数组arr2
第二层循环arr2: 计算数组中两个数的6种结果,将这6种计算结果分别替换原数组的两个数。每次循环返回一个6X1的二维数组arr1
第三层循环arr1: 判断数组中仅剩的1个数是否等于24,若是,将其结果push到res中

2.代码

代码如下(示例):

//计算公式的构造函数
function Equation(equa, res) {
    this.equa = equa;
    this.res = res;
}
//两个数计算的6种结果
function count(a, b) {
    let arr = [];
    arr.push(new Equation(`(${a.equa})+(${b.equa})`, a.res + b.res));
    arr.push(new Equation(`(${a.equa})-(${b.equa})`, a.res - b.res));
    arr.push(new Equation(`(${b.equa})-(${a.equa})`, b.res - a.res));
    arr.push(new Equation(`(${a.equa})*(${b.equa})`, a.res * b.res));
    if (b.res) {
        arr.push(new Equation(`(${a.equa})/(${b.equa})`, a.res / b.res));
    }
    if (a.res) {
        arr.push(new Equation(`(${b.equa})/(${a.equa})`, b.res / a.res));
    }
    return arr;
}

//从M个数中取2个数,计算其结果,并替换原数组参与计算的数
function takeNumCalc(arr) {
    let res = []; //所有取数和计算的结果
    let falg = new Array(4).fill(0); //标记数组
    let path = []; //每次取数的集合
    function backTracking(startIndex) {
        if (path.length == 2) {
            //1.得到数组中没有参与计算的数
            let newarr = arr.filter((val, index) => falg[index] == 0);
            //2.获取此次组合数的6种计算结果
            let countres = count(...path);
            //3.每次遍历返回,计算结果和数组中没有参与计算的数的新数组
            countres.forEach((val) => {
                res.push([...newarr, val]);
            });
            //4.结束此次递归
            return;
        }
        //选数,每次从上次递归的i+1开始
        for (let i = startIndex; i < arr.length; i++) {
            falg[i] = 1;
            path.push(arr[i]);
            backTracking(i + 1);
            falg[i] = 0; //回溯
            path.pop();
        }
    }
    //执行函数
    backTracking(0);
    //返回结果
    return res;
}

let res = []; //最终结果
let arr = [5, 7, 1, 9]; //初始数组,即输入值
//将初始数组转换成Equation对象数组,便于存储计算公式
let arr4 = arr.map((val) => new Equation(val, val));
let arr3 = takeNumCalc(arr4); //得到36X3二维数组
arr3.forEach((val) => {
    let arr2 = takeNumCalc(val); //得到18X2二维数组
    arr2.forEach((val) => {
        let arr1 = takeNumCalc(val); //得到6X1二维数组
        arr1.forEach((val) => {
            if (val[0].res == 24) {
                res.push(val[0]);
            }
        });
    });
});
console.log(res);

3.运行结果

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值