【LeetCode】力扣周赛题目总结

本文解析了LeetCode中的四个问题:删除字符使字符串特殊、判断顺子组合、计算按位或最大子集数和链表中下一个更大节点。涉及字符串处理、双指针技巧、回溯搜索和单调栈算法应用。
摘要由CSDN通过智能技术生成


在这里插入图片描述

1. Leetcode 3085 成为 K 特殊字符串需要删除的最少字符数


本题思考的关键点:

① 在字符串处理放到 cnt[26] 数组中,枚举删除字母后,字母出现的最少次数
逆向思维,直接求最多保留多少个字母

  • 本题示例代码如下:
class Solution {
public:
    int minimumDeletions(string word, int k) {

    int cnt[26] = {0};  
    for (auto x : word)
        cnt[x - 'a'] ++;
        
    sort(cnt, cnt + 26);

    int max_sum = 0;   // 逆向思维,求出最多保留多少个字母的数量

    // 第一层枚举保留的字母  出现的最少次数
    for (int i = 0; i < 26; i ++)
    {
        int sum  = 0;
        // 比字母 i 对应的次数小的字母都要删除
        for (int j = i; j < 26; j ++)
        {
            sum += min(cnt[j], cnt[i] + k);
        }
        max_sum = max(max_sum, sum);
    }
    return word.length() - max_sum;
    }
};


2. Leetcode 846 一手顺子


本题思考的关键点:[双指针 + 枚举]

从小到大进行枚举,枚举当前组的第一个数

② 不断的维护当前的个数即可

  • 本题示例代码如下:
class Solution {
public:
    bool isNStraightHand(vector<int>& hand, int groupSize) {

    if (hand.size() % groupSize != 0)
        return false;

    sort(hand.begin(), hand.end());

    unordered_map<int, int> mymap;
    for (auto x : hand)
        mymap[x] ++;

		// 枚举当前组的第一个数
    for (int i = 0; i < hand.size(); i ++)
    {
        if (mymap[hand[i]] <= 0)  continue;

        int j = hand[i];
        int cnt = 0;
        while (cnt < groupSize)
        {
            cnt ++;
            if (mymap[j] > 0)
            {
                mymap[j] --;
                j ++;
            }
            else 
                return false;
        }
    }
    return true;
    }
};


3. Leetcode 2044 统计按位或能得到最大值的子集数目


本题思考的关键点:[回溯 + 暴搜]

如何枚举,将所有子集的情况都统计进去

② 先把最大的子集异或值求出来,然后想清楚剩下的有多少种

③ 这个暴搜考虑的是选或者不选的

  • 本题示例代码如下:
// 数据范围: n ≤ 30,指数级别, 所以用 dfs + 剪枝  

class Solution {
public:
    int ans = 0;
    int countMaxOrSubsets(vector<int>& nums) {
    
    // 首先算出子集按位或得出的最大值
    int mmax = 0;
    for (auto x : nums)
        mmax |= x;

    // 进行暴搜,注意:此时的 cur 为 0
    dfs(nums, mmax, 0, 0);
    return ans;
    }

    void dfs(vector<int>& nums, int mmax, int index, int cur)
    {
        // 剪枝
        if (cur == mmax)
        {
            ans += (1<<(nums.size() - index));
            return ;
        }

        if (index == nums.size())
            return ;

        dfs(nums, mmax, index + 1, cur | nums[index]);
        dfs(nums, mmax, index + 1, cur);
    }
};


4. Leetcode 1019 链表中的下一个更大节点


本题思考的关键点:[单调栈]

及时的将不用的数据清理出去

  • 本题示例代码如下:
class Solution {
public:
    vector<int> nextLargerNodes(ListNode* head) {
    
    // 取出链表数据,将其变成数组
    vector<int> nums;
    while (head != nullptr)
    {
        nums.push_back(head->val);
        head = head->next;
    }

    vector<int> ans(nums.size());
    stack<int> st;
    // 从右往左遍历
    for (int i = nums.size() - 1; i >= 0; i --)
    {
        int val = nums[i];
        while (!st.empty() && val >= st.top())
            st.pop();

        if (!st.empty())
            ans[i] = st.top();

        st.push(nums[i]);  
    }
    return ans;
    }
};
  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未来可期LJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值