扑克牌顺子

在群里看到一条面试题:

一个表,表中有5个数字,范围在 [0-13]之间,其中0表示扑克牌的王,1-13  表示  2-A,牌肯能重复,王可以代替任何牌,
判断这5张牌能否凑成一个顺子?

首先考虑排序,排序之前要检查数组是否有非0重复项 ,如果有 肯定不是顺子,如果有重复为0的情况,就要对比0的个数 和需要的0的个数了。

排除了重复项,要判断是不是有 0,有1,(有0可以代替任何牌,有1需要考虑 10,11,12,13,1的情况)

排除了0和1的情况 ,就是直接判断 是不是顺子 就好了。我这里用 map 和filter 函数实现。
代码如下

function isShunZi(arr){
	
	arr.sort((a,b)=>(a - b));	//数组排序
	
	const index = arr.indexOf(0);  //获得首个0的索引
	const lastIndex = arr.lastIndexOf(0);//获得最后一个0的索引
	
	if(index !== lastIndex){  //多个0的情况
		arr.splice(0,lastIndex + 1);
		return checkSort(arr,lastIndex + 1);
	}
	
	if(arr[0] === 1){  //没有0  且有1  只能出现  12345 或者 10,11,12,13,1
		if(arr[1] === 2 || arr[1] === 10){
			arr.splice(0,1);
			return checkSort(arr,0);
		}else{
			return false;
		}
	}
	if(arr[0] === 0){  //只有一个0
		if(arr[1] === 1 ){
			if(([10,11,12,13].indexOf(arr[2])>=0) && (arr[2]>9)){
				arr.splice(0,2);
				return checkSort(arr,1);
			}
		}
		arr.splice(0,1);
		return checkSort(arr,1);
	}
	return checkSort(arr,0);  //没有0
	function checkSort(arr,count){  //count表示原数组中0的个数, arr 是删除0之后的数组
		const newArr = arr.map(function(el,index,arr){
			if(index == arr.length-1){
				return 1
			}
			const next = arr[index + 1];
			return next - el;
		})
		.filter(function(value){
			return value >= 2
		});
		
		let spaceCount = 0;
		if(newArr.length>0){	
			spaceCount = newArr.reduce(function(a,b){
				return a + b;
			}) - newArr.length;
		}
		return spaceCount <= count
	}
}

我这里定义了13个数组验证

全部代码如下

 var arrs = [
 [1,2,3,4,5],   //true
 [2,0,8,10,13],  //false
 [11,10,13,1,12],  //true
 [0,2,3,5,6],  //true
[0,1,13,11,10],  //true
[0,1,10,11,13],  //true
 [4,6,7,8,0],  //true
 [0,1,2,3,7],  //false
 [2,5,9,8,6],//fasle
 [4,5,6,7,8],//true
 [1,10,11,12,13], //true
 [0,0,1,5,3], //true
 [0,0,1,2,5], //true
 [0,1,1,5,7], //false
 [0,0,0,0,0], //true

 ];


function isShunZi(arr){
	
	arr.sort((a,b)=>(a - b));	//数组排序
	
	const index = arr.indexOf(0);  //获得首个0的索引
	const lastIndex = arr.lastIndexOf(0);//获得最后一个0的索引
	
	if(index !== lastIndex){  //多个0的情况
		arr.splice(0,lastIndex + 1);
		return checkSort(arr,lastIndex + 1);
	}
	
	if(arr[0] === 1){  //没有0  且有1  只能出现  12345 或者 10,11,12,13,1
		if(arr[1] === 2 || arr[1] === 10){
			arr.splice(0,1);
			return checkSort(arr,0);
		}else{
			return false;
		}
	}
	if(arr[0] === 0){  //只有一个0
		if(arr[1] === 1 ){
			if(([10,11,12,13].indexOf(arr[2])>=0) && (arr[2]>9)){
				arr.splice(0,2);
				return checkSort(arr,1);
			}
		}
		arr.splice(0,1);
		return checkSort(arr,1);
	}
	return checkSort(arr,0);  //没有0
	function checkSort(arr,count){  //count表示原数组中0的个数, arr 是删除0之后的数组
		const newArr = arr.map(function(el,index,arr){
			if(index == arr.length-1){
				return 1
			}
			const next = arr[index + 1];
			return next - el;
		})
		.filter(function(value){
			return value >= 2
		});
		
		let spaceCount = 0;
		if(newArr.length>0){	
			spaceCount = newArr.reduce(function(a,b){
				return a + b;
			}) - newArr.length;
		}
		return spaceCount <= count
	}
}

//测试函数
function run(arrs){
	for(let i =0;i<arrs.length;i++){
		let res = isShunZi(arrs[i])
		console.log(res,'res'+i)
	}
}
run();

这里我考虑还有另一种思路 : 列出所有可能的组合 看给定的 在不在这个组合中 。有时间再实践一下。

总结

首先应该整体分析需求的多种情况,通过画图什么的理解你的函数应该怎样设计。
避免想当然的想到哪里写到哪里,这个例子,我写了三遍,才到现在这个样子,当然还有值得优化的地方。
这里用了好几个 map filter reduce 都是遍历方法,性能上会不会有影响?
测试,测试的不是很具有代表性。
就先写到这里吧,有时间再想想怎么优化代码,不足的地方还很多,欢迎批评指正。

原文地址:https://www.cnblogs.com/chengyunshen/p/10450381.html