【剑指offer】扑克牌中的顺子+不用加减乘除做加法

🔥题目

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

输入:[2, 3, 4, 5, 6]
输出:true

输入:[0, 0, 1, 2, 5]
输出:true

☘️解析

理清题意后,我们分析出5张牌是顺子的充要条件为:

1)除大小王外,不能有重复
2)除大小王外,最大值max和最小值min满足:max - min < 5

第二个条件是解题的神来之笔:

没有大小王时,假设五张牌为[1, 2, 3, 4, 5],很容易看出最大最小值之差小于5;有大小王时,假设五张牌为[0, 0, 1, 2, 4],也可以看出最大最小值之差只会更小,不会更大。

这一个判断妙在何处呢?

一来,排除了大小王的干扰;
二来,找最大值/最小值并不需要数组有序,是O(n)的复杂度。

🧊代码
class Solution {
    public boolean isStraight(int[] nums) {
        int min = Integer.MAX_VALUE;
        int max = 0;
        Set<Integer> set = new HashSet<>();
        for (int num : nums) {
            if (num == 0) {
                continue;
            }
            if (set.contains(num)) {
                return false;
            }
            set.add(num);
            min = Math.min(min, num);
            max = Math.max(max, num);
        }
        return max - min < 5;
    }
}
🌸补充

妙哉妙哉!

 
 
 
 
 

🔥题目

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

输入:a = 1,b = 1
输出:2

☘️解析

竟然真的有加减乘除,只使用位运算,也能实现加法 ?!

联想一下数字电路中最简单的1位加法器:

absumcarry
0000
0110
1010
1101

sum = a ^ b

进位 carry = (a & b) << 1

因此:a + b = sum + carry

左侧的加法不断被转化为右侧的加法,直到进位为0。

如果你还是不理解这个过程,就用 3 + 7 试试看,这是非常经典的例子。

🧊代码

按照上面的思路写出代码:

class Solution {
    public int add(int a, int b) {
        int sum = a ^ b;
        int carry = ((a & b) << 1);
        while (carry != 0) {
            carry = ((a & b) << 1);
            sum = a ^ b;
            a = sum;
            b = carry;
        }
        return sum;
    }
}

代码可进一步精简:

class Solution {
    public int add(int a, int b) {
        while (b != 0) {
            int temp = a ^ b;
            b = ((a & b) << 1);
            a = temp;
        }
        return a;
    }
}
🌸补充

妙哉妙哉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值