下面是卡牌分组题目,原题详见LeetCode卡牌分组
算法步骤:
step1.统计重复卡牌的数量。
step2.利用递归求出两种卡牌的最大公约数。
step3.同理,求出所有卡牌的最大公约数。
step4.得到结果。若最终的最大公约数大于1,说明卡牌可以分组。
源代码card_combination.js:
export default (arr)=>{
//step1.利用reduce()求得重复的卡牌数量
let objRepeat = arr.reduce(function(prev,next){
prev[next] = (prev[next]+1)||1;
return prev;
},{});
var cardGroup = Object.values(objRepeat);//用于存储卡牌重复的数目
//step2.求得两种卡牌之间的最大公约数
//源自y=ax与y=ax+b
let gcd = (a, b) => {
if (b === 0) {
return a
} else {
return gcd(b, a%b);
}
}
//step3.求得所有卡牌的最大公约数
while(cardGroup.length>1){
let first = cardGroup.shift();
let second = cardGroup.shift();
console.log(first,second);
let result = gcd(first,second); //求得两张卡牌得最大公约数
if(result===1){
return false; //说明最大公约数是1
}else{
//将求得的公约数放回去,判断其余卡牌的公约数是否是该公约数。其中'0'不是唯一的,可以任意数值。主要是要判断length
cardGroup.unshift(result);
}
}
// step4.得出结论。若最终的最大公约数大于1,说明卡牌可以分组。
return cardGroup.length?cardGroup[0]>1:false;//全部卡牌的最大公约数已经求完,判断最终的最大公约数是都大于1
}
测试代码card_combination.test.js:
import cardCombination from '../../src/chapter2_array/card_combination';
test('卡牌分组',()=>{
expect(cardCombination([1,1,2,2,2,2])).toEqual(true);
})
经测试,本算法能得到示例中所有的输出结果。具体效果,请自行测试。
本算法基于jest测试工具进行测试,教程详见使用Jest测试JavaScript