因为第一批笔试的缘故加上自己家里买的摄像头还在路上,所以这一次的笔试我是没有参加的,根据网上整理出来的题目描述自己完成了这两道算法题。因为自己这样做,并没有得到验证,如果哪里有误的地方还希望大家能够积极指正。
题目描述
有一叠扑克牌,每张牌介于1和10之间
有四种出牌方法:单出1张
出2张对子
出五张顺子,如12345
出三连对子,如112233给10个数,表示1-10每种牌有几张,问最少要多少次能出完
题目分析
这个题目如果需要找特定的规则去判断,显然是可以的,但是条件有点多。所以就不考虑这种方式,干脆根据题目中的几种情形分别去回溯,然后对回溯的结果去比较,选择最小的一种方式来打牌。
能出三个对子,显然需要要求,i,i+1,i+2的数目都大于2。同理,要出顺子也要满足一定的条件,我们只需要对该条件进行分别进行判断即可。
大致整理一下代码的核心思路,从小往大出牌,研究每一个数字可以如何出完。如果不能打连对或者连子的时候,出牌的次数是一定的,如果可以打的时候,计算打连对最少需要出的次数,打连子最少出的次数,然后打对子最少需要出的次数,然后最终取最小,就是出完当前数字的最少次数,然后依次计算每个数字出完的最小次数。
这里我只给出核心代码,也并没有处理输入输出的情况。大家自行处理。
python代码
class Solution1:
def leastTimes(self,nums,begin=0):
res=sum(nums[begin:]) # 表示剩余牌的总数
if not res:return 0
if nums[begin]>0:
if begin+2<10 and nums[begin]>1 and nums[begin+1]>1 and nums[begin+2]>1:
for i in range(begin,begin+3): # 打了连对,状态改变
nums[i]-=2
res=min(1+self.leastTimes(nums,begin),res)
for i in range(begin,begin+3): # 回溯,恢复状态
nums[i]+=2
if begin+4<10 and nums[begin+1] and nums[begin+2] and nums[begin+3] and nums[begin+4]:
for i in range(begin, begin + 5): # 打了连子,状态改变
nums[i] -= 1
res=min(1+self.leastTimes(nums,begin),res)
for i in range(begin, begin + 5): # 回溯,恢复状态
nums[i] += 1
if nums[begin]>1:
nums[begin] -= 2 # 出对子,因为出对子之后,可能当前的牌还有剩余,所以继续从当前牌型去搜索。
return min(1+self.leastTimes(nums,begin),res)
else : # 只有一张,只能考虑单张
return min(res,1+self.leastTimes(nums,begin+1