Javascript算法练习(八)

Javascript算法练习(八)

updateInventory,更新库存,即用新的数组数据去更新老的数组数据

  • 思路:遍历新数组中的数据

    • 更新老数据:根据名称去老数组中查找,找到了就用对应的数量与老的相加;
    • 添加新数据:如果没找就将新数组中的数据添加到老数组中;
    /**
     * 11. 用第二个数组的数据去更新第一个数组数据(更新库存)
     * @param  {Array} oldArr 原始数据
     * @param  {Array} newArr 新数据
     * @return {Array}        返回更新后的老数据数组并且根据名称排序后的二维数组
     *
     * PS: 1. 两个数组都是二维数组
     *     2. 两个数组的内容要一致即元素的第一个元素为数量,第二个元素为名称,
     *         比如:oldArr = [[22, "hello"]], newArr = [[33, "hello"]];  更新后就是:[[55, "hello"]]
     */
    ArrayHandler.prototype.updateInventory = function (oldArr, newArr) {
    
        if (!oldArr || !newArr) return;
    
        var compare = function (a, b) {
            var ua = a[1].toUpperCase();
            var ub = b[1].toUpperCase();
    
            if (ua < ub) {
                return -1;
            }
    
            if (ua > ub) {
                return 1;
            }
    
            if (ua == ub) {
                return 0;
            }
        };
    
        if (oldArr.length === 0) return newArr.sort(compare);
    
        if (newArr.length === 0) return oldArr.sort(compare);
    
        var findFlag = 0; // 找到存在的库存标识
    
        newArr.map(function (newValue) {
    
            oldArr.map(function (oldValue) {
                if (oldValue[1] == newValue[1]) {
                    oldValue[0] += newValue[0]; // 同类产品库存数累加
                    findFlag = 1;
                    return;
                }
            });
    
            // 到这里表示没有库存,直接添加
            if (!findFlag) {
                oldArr.push(newValue);  // 新产品直接添加
            }
    
            // 复位库存标识
            findFlag = 0;
        });
    
        // 排序
        oldArr.sort(compare);
    
        return oldArr;
    }

checkCashRegister:模拟收银抽屉,给出购买的物品价格及所付金额,算出找零

  • 思路:

    • 先定义好金钱面值(这个与国家相对应,每个国家的面值不同,并且基本上不会有所改变,此例以美元为准),这里需要注意,将所有面值按一美元为单位乘以基数(如:100),避免用浮点数去操作避免因精度问题,最后得到的值不正确;
    • 然后用所付款金额减去购物需付款得到找零金额,最后去面值数组中,从高到底的去取值;
    • 通过对找零金额取余和取除数,得到相应面值金额所需要找出的张数;
    
    /**
     * 9. 模拟收银抽屉,给出购买的物品价格及所付金额,算出找零
     * @param  {Number} price 商品价格
     * @param  {Number} cash  所付金额
     * @param  {Array} cid   剩余金额的二维数组
     * @return {Array}       返回需要找零的金额的二维数组,里面包含了找零对应的面值
     *
     * 最后一个参数cid,即面值剩余金额数组,必须要和国家钱币对应的面值金额相一致,且顺序从小到大排
     * 例如:[ 
     *         // 对应1美分(Cent)、5美分(Nickel)、10美分(Dime,一角)、25美分(Quarter)、
     *         // 1美元(ONE)、5美元(FIVE)、10美元(TEN)、20美元(TWENTY)、100美元(ONE HUNDRED)
     *         ["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.10], ["QUARTER", 4.25], 
     *         ["ONE", 90.00], ["FIVE", 55.00], ["TEN", 20.00], ["TWENTY", 60.00], ["ONE HUNDRED", 100.00]
     *       ]
     *
     * TODO:最后可以将dollar数组,当成参数传进去,与cid数组的内容顺序要一致,分别表示钱币金额面值数,
     *     根据基数base和国家钱币面值不同,数组会不相同
     */
    NumberHandler.prototype.checkCashRegister = function (price, cash, cid) {
    
        // 刚刚好
        if (price == cash) return "No Need Back";
    
        // 付款不足
        if (price > cash) return "Need More Money";
    
        var base        = 100;      // 金额基数
        var change      = (cash - price) * base; // 找零
    
        var getTotalMoney = function (arr) {
            var totalMoney = 0;
            arr.reduce(function (preV, currV, currIndex, array){
                totalMoney += base * (preV[1] + currV[1]);
                return currV;
            });
    
            return totalMoney;
        }
    
        // 余额不足,没法找了
        var remain = getTotalMoney(cid);
    
        if (remain == change) { // 零钱刚好找完了
            return "Closed";    
        } else if (remain < change) { // 没钱找了
            return "Insufficient Funds - 1";
        }
    
        // 分别对应,1美分-5美分-1角-25美分-1美元-5美元-10美元-20美元-100美元
        // 这里还可以进行优化,让dollar成为参数,而动态获取相应国家的金额面值
        // 比如代表中国的:[10, 50, 100, 500, 1000, 2000, 5000, 10000] -> 
        // 对应:1角-5角-1元-5元-10元-20元-50元-100元(以元为单位的基础上乘以面值基数:base这里为100)
        var dollar      = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000]; // TODO
        var pay         = {};   // 保存的key:dollar中面值索引,value:要找的此面值的个数
        var currLast    = 0;    // 当前面值所剩余额
        var currMoney   = 0;    // 当前金钱面额(dollar中对应的值)
        for (var i = dollar.length - 1; i >= 0; i--) {
    
            // 当前面值剩余金额
            currLast = cid[i][1] * base;
    
            // 当前面值的金额剩余0,跳过
            if (currLast <= 0) { 
                continue;
            }
    
            // 当前金额面值
            currMoney = dollar[i];
    
            // 达到找零的面值必须满足两个条件:
            // 1. 找零必须大于当前面值
            // 2. 剩余的当前面值的钱足够的情况下
            if (change > currMoney) {
                if (change < currLast) { 
                    // 找零小于当前面值剩余金额
                    pay[i + ""] = parseInt(change / currMoney);
                    change -= currMoney * pay[i + ""];
                } else {
                    // 找零大于当前面值剩余金额,则将所有剩余金额找出
                    pay[i + ""] = parseInt(currLast / currMoney);
                    change -= currLast; // 就直接减去当前面值剩余所有金额
                }
            }
        }
    
        var res = [];
        // 组织最后需要找零的钱
        var keys = Object.keys(pay);
        var idx = 0;
        for (var j = 0; j < keys.length; j++) {
    
            // 需要找零的面值索引
            idx = parseInt([keys[j]]);
    
            // 该面值最后找出的零钱(公式:面值 * 需要找出数量 / 金钱面值基数)
            cid[idx][1] = dollar[idx] * pay[keys[j]] / base;
    
            console.log("-------- " + cid[idx][1]);
            res.unshift(cid[idx]);
    
            // total += dollar[idx] * pay[keys[j]]; // 这里计算的结果应该和最开始需要找零的金额一致
        } 
    
        // 找到最后,所有能找的面值加起来还不够
        // 这里与最开始不同,这里是过滤掉了所有找不开的面值
        // 比如:要找0.05元,但是目前剩余一张0.01和1元的面值,依旧判定为找不开
        // 而最开始的是所有余额加起来都不够找
        if (getTotalMoney(res) < change) {
            return "Insufficient Funds - 2";
        }
    
        return res;
    }

getPermutation:获取字符串的所有排列结果,返回所有结果组成的字符串数组

  • 思路:这里主要还是考察到递归的使用,还是有点不太明白,虽然整出结果来了,还需好好深入递归去研究研究下

    
    /**
     * 5. 获得指定字符串的所有排列结果的数组
     * @return {[type]} [description]
     */
    StringHandler.prototype.getPermutation = function () {
    
        var resArr      = [];
    
        return function perm(str, start) {
    
    
            var permArr     = str.split("");
            var end         = permArr.length;
    
            for (var j = start; j < end; j++) {
    
                // 交换数组中两个索引位置的值
                swap(permArr, j, start);
    
                // 保存交换后的字符串,如果曾经保存过则过滤掉,避免重复
                var tmpStr = permArr.join("");
                if (resArr.indexOf(tmpStr) == -1) {
                    resArr.push(tmpStr);
                }
    
                // 重置交换起始位置,递归直到最后一位字符结束,即:start > end
                perm(tmpStr, start + 1, end);
            }
    
            return resArr;
        };
    }();

总结

最近有点松懈了,加上组里现在整个模块的业务都让我一个人搞,老大跑去做维护新系统去了,所以最近也很忙(借口总是很多,呸………..!!!),还是要加紧学习,打好基础,不能松懈了。今天整了这三个练习,记录下,还算有点收获吧。给自己打打气,加油吧!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若叶岂知秋vip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值