剑指offer(C++)-JZ61:扑克牌顺子(算法-模拟)

简介: 剑指offer(C++)-JZ61:扑克牌顺子(算法-模拟)

题目描述:

现在有2副扑克牌,从扑克牌中随机五张扑克牌,我们需要来判断一下是不是顺子。

有如下规则:

1. A为1,J为11,Q为12,K为13,A不能视为14

2. 大、小王为 0,0可以看作任意牌

3. 如果给出的五张牌能组成顺子(即这五张牌是连续的)就输出true,否则就输出false。

4.数据保证每组5个数字,每组最多含有4个零,数组的数取值为 [0, 13]


要求:空间复杂度 O(1),时间复杂度O(nlogn),本题也有时间复杂度O(n) 的解法

示例:

输入:

[6,0,2,0,4]


返回值:

true


说明:

中间的两个0一个看作3,一个看作5 。即:[6,3,2,5,4]

这样这五张牌在[2,6]区间连续,输出true


解题思路:

本题考察算法场景模拟。两种解题思路。


1)排序法


      将卡牌排序,复杂度O(nlogn),遍历一次O(n),记录0的数量,如果出现重复数据则中断返回false,对非0非重复数据进行间隔累加。如果最终0的数量大于等于间隔累加数,则说明可以形成顺子。


      比如2 0 4 0 0 7,排序后0 0 0 2 4 7,2和4间隔1,4和7间隔2,三个0刚好补齐,多余的0可以在前后凑顺子。


     如果0的数量和输入数量一致,则无法形成顺子。


     总的复杂度O(nlogn+n),即O(nlogn)。


2)查找法


      进行双层循环。发现0则跳过;通过set的count函数检测是否遇到重复,重复则返回false;无问题则插入数值,同时刷新最值。


      如果能持续到循环结束,此时最大值减去最小值的差值小于5,则一定能构成顺子,反之则不行。


      时间复杂度O(n2),遍历为n,查找为n,即n*n。


3)查找法进阶


      与查找法流程基本一致,区别在于检测重复值。因为卡牌最多只有0-14这15个数字,我们充分利用位运算特性,如果遇到某个数值,比如5,则将bm的第五位设为1,即0001 0000,每次遇到一个新数值就刷新bm。


      这样可以用&运算检测是否重复,只有某一位都为1,才会触发重复标识,进而返回false。用|运算刷新bm。


      时间复杂度O(n),遍历为n,查找为1,即n*1。

测试代码:

1)排序法

class Solution {
public:
    // 是否顺子
    bool IsContinuous(vector<int>& numbers) {
        // 排序法
        // 时间复杂度O(nlogn+n)=O(nlogn)
        // 快速排序
        sort(numbers.begin(), numbers.end());
        int size = int(numbers.size());
        int zeroNum = 0;
        int diff = 0;
        for(int i = 0; i < size; ++i){
            // 记录0的数量
            if(numbers[i] == 0){
                zeroNum++;
            } 
            // 判断是否有重复数据
            else if(i > 0 && numbers[i - 1] == numbers[i]){
                return false;
            }
            // 累加间隔长度,注意0不参与间隔计算
            else if(i > 0 && numbers[i - 1] != 0){
                // 比如2和3之间无多余间隔,则diff累加0;2和4之间有3这一个间隔,diff累加1
                diff += numbers[i] - numbers[i - 1] - 1;
            }
        }
        // 0的数量只有大于等于多余的间隔长度,才能凑成顺子
        if(zeroNum == size){
            return false;
        }
        else if(zeroNum >= diff){
            return true;
        }
        else{
            return false;
        }
    }
};

2)查找法

class Solution {
public:
    // 是否顺子
    bool IsContinuous(vector<int>& numbers) {
        // 查找法
        // 时间复杂度O(n2)
        int size = int(numbers.size());
        set<int> s;
        int minNum = 13;
        int maxNum = 0;
        for(int i = 0; i < size; ++i){
            // 跳过0
            if(numbers[i] == 0){
                continue;
            } 
            // 检查重复值,复杂度O(n)
            if(s.count(numbers[i])){
                return false;
            }
            // 插入
            s.insert(numbers[i]);
            // 刷新最值
            minNum = min(minNum, numbers[i]);
            maxNum = max(maxNum, numbers[i]);
        }
        // 最大值和最小值之差小于5,则一定能构成顺子
        bool result = (maxNum - minNum) < 5;
        return result;
    }
};

3)查找法进阶

class Solution {
public:
    // 是否顺子
    bool IsContinuous(vector<int>& numbers) {
        // 查找法进阶
        // 时间复杂度O(n)
        int size = int(numbers.size());
        int bm = 0;
        int minNum = 13;
        int maxNum = 0;
        for(int i = 0; i < size; ++i){
            // 跳过0
            if(numbers[i] == 0){
                continue;
            } 
            // 检查重复值,复杂度O(1)
            if((bm & (1 << numbers[i])) != 0){
                return false;
            }
            // 数字对应位改为1
            bm |= (1 << numbers[i]);
            // 刷新最值
            minNum = min(minNum, numbers[i]);
            maxNum = max(maxNum, numbers[i]); 
        }
        // 最大值和最小值之差小于5,则一定能构成顺子
        bool result = (maxNum - minNum) < 5;
        return result;
    }
};


相关文章
|
1月前
|
机器学习/深度学习 安全 算法
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
|
1月前
|
人工智能 算法 测试技术
【数学】【排序】【C++算法】3027人员站位的方案数
【数学】【排序】【C++算法】3027人员站位的方案数
|
2月前
|
存储 算法 Serverless
【C/C++ 数据结构】深入探索数据结构中算法复杂度:从C++和数学的视角
【C/C++ 数据结构】深入探索数据结构中算法复杂度:从C++和数学的视角
47 0
|
2月前
|
算法 数据处理 C++
【C++ 20 新特性 算法和迭代器库的扩展和泛化 Ranges】深入浅出C++ Ranges库 (Exploring the C++ Ranges Library)
【C++ 20 新特性 算法和迭代器库的扩展和泛化 Ranges】深入浅出C++ Ranges库 (Exploring the C++ Ranges Library)
109 1
|
2月前
|
缓存 算法 C语言
【C++ 标准查找算法 】C++标准库查找算法深入解析(In-depth Analysis of C++ Standard Library Search Algorithms)
【C++ 标准查找算法 】C++标准库查找算法深入解析(In-depth Analysis of C++ Standard Library Search Algorithms)
49 0
|
18天前
|
存储 缓存 算法
C++从入门到精通:4.6性能优化——深入理解算法与内存优化
C++从入门到精通:4.6性能优化——深入理解算法与内存优化
|
18天前
|
存储 算法 程序员
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
|
24天前
|
算法 DataX
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
|
1月前
|
人工智能 算法 BI
【图论】【 割边】【C++算法】1192. 查找集群内的关键连接
【图论】【 割边】【C++算法】1192. 查找集群内的关键连接
|
1月前
|
算法 测试技术 C#
【模拟】【C++算法】2826. 将三个组排序
【模拟】【C++算法】2826. 将三个组排序