leetcode846. 一手顺子

该博客探讨了如何通过哈希表统计和队列滑动窗口两种方法解决LeetCode中的1296题——将整数数组重组为指定大小的连续子序列。文章详细解释了两种算法的实现思路,强调了判断条件和优化技巧,并提供了完整的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://leetcode-cn.com/problems/hand-of-straights/

题意:

爱丽丝有一手(hand)由整数数组给定的牌。 

现在她想把牌重新排列成组,使得每个组的大小都是 W,且由 W 张连续的牌组成。

如果她可以完成分组就返回 true,否则返回 false。

注意:此题目与 1296 重复:https://leetcode-cn.com/problems/divide-array-in-sets-of-k-consecutive-numbers/

方法一:哈希表统计(效果一般)

class Solution {
public:
    bool isNStraightHand(vector<int>& hand, int groupSize) {
        int len = hand.size();
        map<int,int> mp;//哈希表
        if(len%groupSize!=0) return false;//如果长度不是groupSize的整数倍,说明不是所要的
        sort(hand.begin(),hand.end());
        for(auto& num:hand)
        {
            mp[num]++;
        }
        for(auto iter=mp.begin();iter!=mp.end();iter++)
        {
            if(iter->second==0)//匹配数目为0,要么是匹配完了,要么是没有这个数
                continue;
            else
            {
                int val = iter->second;//val记录当前key值对应的的value值
                int index = 0;
                while(index<groupSize)//遍历后续的几个键值
                {
                    mp[iter->first+index]-=val;
                    if(val<0)//不够减,说明凑不了,返回false
                        return false;
                    index++;
                }
            }
        }
        return true;//能遍历完,说明都匹配过了
    }
};

方法二:队列+滑动窗口(效果最优)

class Solution {
public:
    bool isNStraightHand(vector<int>& hand, int W) {
        int n = (int)hand.size();
        if (n % W) return false;
        int left = 0, right = 0;//相同值元素的左右端点,左闭右开[left,right)
        sort(hand.begin(), hand.end());//元素排序
        deque<int> window; //用来保存滑动窗口中的元素个数
        deque<int> nums; //用来保存滑动窗口中的元素值
        while (right < n) {
            while (right < n && window.size() < W) { //没达到滑动窗口大小W,继续添加元素
                while (right < n && hand[left] == hand[right]) right++; //相同元素值,继续找右端点
                window.push_back(right-left); //保存当前元素个数
                nums.push_back(hand[left]);//保存当前元素值
                left = right;//下一个元素起始位置
            }
            if (window.size() < W) return false; //滑动窗口内元素个数达不到W,结束
            for (int i = 1; i < W; i++) { //找到一组顺子
                window[i] -= window[0]; //所有元素减去相同的频率,剩下的可以用于下面的顺子组合
                if (window[i] < 0 || nums[i] != nums[i-1] + 1) return false; //元素不够用或者相邻元素值相差不为1无法组成顺子,结束
            }
            window.pop_front();//移除首个元素个数
            nums.pop_front();//移除首个元素
            while (!window.empty() && window[0] == 0) { //继续移除元素个数为0的元素
                window.pop_front();
                nums.pop_front();
            }
        }
        return true;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值