力扣周赛 503

Q1.限制有序数组中的元素出现次数

🔗 https://leetcode.cn/contest/weekly-contest-503/problems/limit-occurrences-in-sorted-array/description/

题目

  • 给定升序整数数组 nums 和整数 k
  • 返回去重后每个元素最多保留 k 个的数组(保持原顺序)

思路

  • 模拟

代码

cpp 复制代码
class Solution {
public:
    vector<int> limitOccurrences(vector<int>& nums, int k) {
        vector<int> ans;
        int cnt = 1;
        ans.push_back(nums[0]);
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] == nums[i-1]) 
                cnt++;
            else
                cnt = 1;
            if (cnt <= k) {
                ans.push_back(nums[i]);
            }
        }
        return ans;
    }
};

Q2. 密码强度

🔗 https://leetcode.cn/contest/weekly-contest-503/problems/password-strength/description/

题目

  • 给定字符串 password
  • 按出现过的不同字符计分并求和:小写字母 1分,大写字母 2分,数字 3分,特殊字符 5分
  • 返回总分

思路

  • 模拟

代码

cpp 复制代码
class Solution {
public:
    int passwordStrength(string password) {
        int ans = 0;
        set<char> s;
        for (char ch : password) {
            if (s.count(ch)) continue;
            s.insert(ch);
            if (ch >= '0' && ch <= '9') ans += 3;
            if (ch >= 'a' && ch <= 'z') ans += 1;
            if (ch >= 'A' && ch <= 'Z') ans += 2;
            if (ch == '!' || ch == '@' || ch == '#' || ch == '$') ans += 5;
        }
        return ans;
        
    }
};

Q3. 排序排列的最少操作数

🔗 https://leetcode.cn/contest/weekly-contest-503/problems/minimum-operations-to-sort-a-permutation/description/

题目

  • 给定 [0..n-1] 的一个排列 nums
  • 每次只能"反转整个数组"或"左旋一位"
  • 返回将其排成升序的最少操作次数,无法排序则返回 -1

思路

  • 最终都升序,需要当前的梯度变化仅一次
  • 即若当前都升序,仅存在一处降序;反之,若当前都降序,仅存在一处升序;都在首位相交的地方;
  • 找到升序开始的位置 idx,也就是 0 的位置,调整的方案:
    • 左旋 idx 次
    • 先反转,再左旋 len - idx 次,再反转
  • 找到降序开始的位置 idx,调整的方案:
    • 左旋 idx 次,反转
    • 反转,左旋 len - idx 次

代码

cpp 复制代码
class Solution {
public:
    int minOperations(vector<int>& nums) {
        int len = nums.size();
        if (len == 1) return 0;
        vector<int> n(nums);
        for (auto num : nums) {
            n.push_back(num);
        }
        int asc = 1, dsc = 1;
        int max_asc = -1, max_dsc = -1;
        for (int i = 1; i < n.size(); i++) {
            if (n[i] > n[i-1]) {
                asc++;
                dsc = 1;
            } else {
                asc = 1;
                dsc++;
            }
            if (max_asc == -1 && asc == len) max_asc = i;
            if (max_dsc == -1 && dsc == len) max_dsc = i;
        }

        if (max_asc == -1 && max_dsc == -1) return -1;
        int ans = n.size();
        if (max_dsc != -1) {
            int idx = max_dsc - len + 1;
            ans = min(ans, idx + 1); // 左旋 idx + 反转
            ans = min(ans, 1 + len - idx); // 反转 + 左旋
        }
        if (max_asc != -1) {
            int idx = max_asc - len + 1;
            ans = min(ans, idx); // 左旋
            ans = min(ans, 2 + len - idx); // 反转 + 左旋 + 反转
        }
        return ans;
        
    }
};

Q4. 递增后的数对数量

🔗 https://leetcode.cn/contest/weekly-contest-503/problems/number-of-pairs-after-increment/

题目

  • 给定数组 nums1nums2 和查询 queries
  • 支持两种操作:
    • 区间加(将 nums2[x..y] 每个元素加 val);
    • 计数(统计满足 nums1[j] + nums2[k] == tot 的下标对 (j,k) 数量)
  • 返回每次计数查询的结果数组

思路

  • 暴力必定 TLE,nums1 的长度不超过 5,核心就是精简对 num2 上的操作,采用分块法
  • 每个块上的 add_val,就记做一个整体,块两边的,逐个更新;
  • 块大小的最优解为 sqrt(num2.size()),作为一种平衡
  • 注意:map 直接 count 不存在的元素,会插入元素,对性能有影响

代码

cpp 复制代码
class Solution {
public:
    vector<int> numberOfPairs(vector<int>& nums1, vector<int>& nums2, vector<vector<int>>& queries) {
        struct Block {
            unordered_map<long long, int> freq;
            long long lazy_val;
            
        };

        // init block with map & lazy_val
        int n = nums2.size();
        int size = sqrt(n);
        int B = (n + size - 1) / size;
         vector<long long> arr(n); 

        vector<Block> block(B);
        for (int i = 0;i < n; i++) {
            arr[i] = nums2[i]; 
            block[i / size].freq[nums2[i]]++;
            block[i / size].lazy_val = 0;
        }

        // process queryies
        vector<int> ans;
        auto add = [&](int x, int y, int val) {
            int l = x / size;
            int r = y / size;
            if (l == r) {
                for (int i = x; i <= y; i++) {
                    if (--block[l].freq[arr[i]] == 0) block[l].freq.erase(arr[i]);
                    arr[i] += val;
                    block[l].freq[arr[i]]++;
                }
                return;
            }

            for (int i = x; i < (l + 1) * size; i++) {                    
                    if (--block[l].freq[arr[i]] == 0) block[l].freq.erase(arr[i]); 
                    arr[i] += val;
                    block[l].freq[arr[i]]++;
                
            }

            for (int i = l + 1; i < r; i++) {
                block[i].lazy_val += val;
            }

            for (int i = r * size; i <= y; i++) {
                    if (--block[r].freq[arr[i]] == 0) block[r].freq.erase(arr[i]); 
                    arr[i] += val;
                    block[r].freq[arr[i]]++;
                
            }
            
        };

        auto count = [&](int tot) {
            int cnt = 0;
            for (int i = 0; i < B; i++) {
                for (int j = 0; j < nums1.size(); j++) {
                    long long target = tot - nums1[j] - block[i].lazy_val;
                    auto it = block[i].freq.find(target);
                    if (it != block[i].freq.end()) {
                        cnt += it->second;
                    }   
                }
            }
            ans.push_back(cnt);
        };

        for (auto query : queries) {
            if (query[0] == 1) {
                add(query[1], query[2], query[3]);
            } else {
                count(query[1]);
            }
        }

        return ans;
    }
};
相关推荐
兰令水1 小时前
leecodecode【面试150】【2026.6.14打卡-java版本】
java·算法·面试
yaoxin5211238 小时前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
noipp8 小时前
推荐题目:洛谷 P10907 [蓝桥杯 2024 国 B] 蚂蚁开会
c语言·c++·算法·编程·洛谷
何极光9 小时前
IDEA集成Maven
java·maven·intellij-idea
程序员二叉9 小时前
【JUC】ThreadLocal底层原理|内存泄漏|弱引用|跨线程传递方案
java·开发语言·面试·职场和发展·juc
程序员二叉9 小时前
【JUC】线程池全套深度详解|参数|流程|拒绝策略|调优|异常处理
java·开发语言·jvm·算法·面试·juc
老马识途2.09 小时前
在AI的帮助下理解spring的启动过程
java·前端·spring
青山木9 小时前
Hot 100 --- 轮转数组
java·数据结构·算法
徐小夕10 小时前
Loop Engineering 深度解析与实战指南(全网最全)
前端·算法·github
Qt程序员10 小时前
掌握 Linux 内核调度:从原理到实现(进程篇)
java·开发语言