Offer 61. 扑克牌中的顺子 (数学 -简单 )

Offer 61. 扑克牌中的顺子

题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

         题目注意事项:1)大小王输入为0但是其实可以为任意牌   2)题目中并没有说明有几副牌,所以每个数字的出现都不一定只有两张或者四张。

思路

       读题可得到的条件

       ⭐  根据顺子是5张连续排的这一特点,可知 最大牌-最小牌<5   如 1 2 3 4 5  5-1=4<5    2 0 0 3 5 5-2=3<5

        ⭐ 且要排除有相同值的情况,如 1 2 2 4 5也满足条件一

       做题的方向

        确定两个基本要考虑的点之后  最主要求 最大值  最小值   以及 如何排除相同情况

             ♥ 题目中的例子可能会给人以误导(输入的数组是增序的),但是根据题目要求,我们是随机抽取的,所以输入的数组实际上是乱序的。但是这也可以给我们提供一个思考方向。

                即 可以首先对输入的数组进行排序,此时最大值位置就确定了  然后遍历求最小值下标以及让相邻的两个值不相等即可。

             ♥ 当我们直接使用乱序的数组,可以通过遍历求得最大值和最小值。那么如何保证没有除0外的相同元素呢,可以使用集合。

复杂度:  时间复杂度O(1)  空间复杂度O(1)   (两种做法的时空复杂度相同)

PS: ① 初始化一个集合 a = set()  增加元素用 add函数

       ② 直接调用python中的sort函数用的是快排  时间复杂度为O(nlogn)

直接使用乱序的数组

'''
    思路:
        例1: 1  2  3  4  5  此时5-1-1=3  代表最大值和最小值中间有三个数  说明5个值肯定是顺序的
        例2: 0  1  2  3  5  因为0可以代表任意值   此时我们跳过0来取最小值和最大值 5-1-1=3 仍然代表最大值和最小值中间有三个数  而0可以填补中间的值
        例3: 2  4  3  0  5  0可以替代1或6  5-2-1 = 2  也可满足要求
        PS1:但是三个例子都有一个问题   最大值最小值肯定是确定的,那么如何保证中间的值是真正递增的呢  例1中间如果不是234,那么应该是223  224等等 就会出现重复数。  例2可能会是0 1 2 2 5
             这时候再考虑重复值的问题即可。
        PS2:问题2是,虽然示例中的nums是按照增序给的  但是题目中并没有说明  应当按照乱序处理。  如 输入的是 [5 1 2 0 3]  [5 3 2 1 4]
    复杂度:时间复杂度O(n)=O(5)=O(1)  空间复杂度O(n)=O(5)=O(1)

    PS: 初始化一个集合 a = set()  增加元素用 add函数
'''
def isStraight(nums):
    minval, maxval, repeat = 14, -1, set()
    for item in nums:
        if item == 0:
            continue
        else:
            minval = min(minval, item)
            maxval = max(maxval, item)
            if item not in repeat:
                repeat.add(item)
            else:
                return False
    if maxval - minval - 1 <= 3:  # 也考虑到了所有元素都为0的情况
        return True
    else:
        return False

对数组进行排序后使用 

'''
    思路:借助于上边的分析   输入一般是乱序的  如果我们排了序后则最大值位置知道,只要求一个最小值以及保证邻近没有重复值即可。
         与思路1对比 相对来说是时间(排序)花费的多一些,而空间(不需要集合了)花费y的少一些。但是由于输入长度已知为5 所以二者的时空复杂度相同都为O(1)
        例:  1  2  3  4  5   当没有0时  最大牌-最小牌 = 4
             0  0  1  2  5   当有0时,忽略掉。 最大值-最小值 = 4
             0  0  1  2  4   当有0时,忽略掉。 最大值-最小值 = 3  
             当然例1 2有以下反例
             0  0  2  2  5  5-2=3<5 但是有两个重复值2,故这时候就要判断相邻的两个值的关系了  如果相等  立刻返回false
    复杂度: 时间复杂度O(nlogn) = O(5log5) = O(1)   空间复杂度O(1)
    PS: 当输入长度一定时,如本题为5  计算可得复杂度为O(1)     
        (最开始想到的是解法2   但是因涉及排序  就采用了解法1,但是其实算下来解法2的复杂度也不高)
'''
def isStraight2(nums):  # nums = [0,13,13,9,12,10]
    nums.sort()  # nums = [0,9,10,12,13,13]
    minind = 0
    for i in range(len(nums) - 1):  # minind = 1 正好对应最小值的小标
        if nums[i] == 0:
            minind += 1
        else:
            if nums[i] == nums[i + 1]:
                return False
    if nums[-1] - nums[minind] < len(nums):
        return True
    else:
        return False

路虽远,行则将至。事虽难,做则必成 。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值