算法--卡牌游戏

318 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

题目

有值为0-9的卡片,每种红、黄、绿、蓝各四张,游戏规则是:出了一张卡片之后可以继续出一张值或者颜色相同的卡片。给你两个长度相同的数组,分别代表卡片的值和卡片的颜色,问一次最多可以出几张卡片

示例:

输入: cardNums = ["1", "4", "3", "4", "5"], cardColors = [ 'r', 'y', 'b', 'b', 'r' ]
输出:3
解析:组合为 4y, 4b, 3b

题解

根据题目意思我们可以了解到我们可以使用一个类似于二叉树的数据结构来解决。左分支就是根据num的数值来查找,右分支就是根据color来查找。

function card(arr1, arr2) {
    const res = [];
    const len = arr1.length;

    for (let i = 0; i < len; i++) {
        const newArr1 = [...arr1];
        const newArr2 = [...arr2];
        newArr1.splice(i, 1);
        newArr2.splice(i, 1);
        res.push(1 + help(arr1[i], arr2[i], newArr1, newArr2, true, true));
    }
    
    return Math.max(...res);
}
function help(cardV, cardC, arr1, arr2, d, f) {
        let count = 0;
        let index;
        if (arr1.length === 0) {
            return 0;
        }
        if (d) {
            index = arr1.indexOf(cardV);
        } else {
            index = arr2.indexOf(cardC);
        }
        if (index === -1) {
            if (!f) 
                return 0;
            }
            count += help(cardV, cardC, arr1, arr2, !d, false);
        } else {
            if (d) {
                cardC = arr2[index];
            }else{
                cardV = arr1[index];
            }
            arr1.splice(index, 1);
            arr2.splice(index, 1);
            count += help(cardV, cardC, arr1, arr2, d, true) + 1;
        }
        return count;
    }
console.log(card(['1', '4', '3', '4', '5'],
                 ['r', 'y', 'b', 'b', 'r']));

代码详解

定义一个数组res来保存每一次遍历的结果,最后返回的时候取最优解即可。

const newArr1 = [...arr1];
const newArr2 = [...arr2];
newArr1.splice(i, 1);
newArr2.splice(i, 1);

这段代码的意义是从数组arr1,arr2中剔除掉当前遍历的卡牌。整体做法是每次找到之后就从数组中删掉抽出的卡牌。

help函数的作用是返回可以抽出的卡牌数量。参数

  • cardV 抽出卡牌的数值
  • cardC 抽出卡牌的颜色
  • arr1 剩余卡牌数值的数组
  • arr2 剩余卡牌颜色的数组
  • d 代表从哪个分支查找 true是数值 false是颜色
  • f 代表上一次是否查找到 如果在两个数值中都没找到的话就会结束

变量count表示找到了多少张卡牌,index 表示在数组中查找到相同值的下标。如果有相同值的卡牌那么,对应的值或颜色就要改变。然后在剔除这张卡牌,循环递归该过程即可。