LeetCode -- 第 359 场周赛(区间问题+动态规划、计数+双指针)

本题我们只需要将所有首字母取出来,并与s比较即可。

class Solution {
public:
    bool isAcronym(vector<string>& words, string s) {
        string res;
        for(auto &it: words) {
            res += it[0];
        }
        return res == s;
    }
};

 

 

 经典哈希表应用,我们要找n个不同的数字,且任意两个数组和不能为k。将i加入答案中同时将k - i加入到哈希表中即可。

class Solution {
public:
    int minimumSum(int n, int k) {
        vector<int> cnts;
        unordered_map<int, int> mp;
        
        
        for(int i = 1; ; i ++ ) {
            if(cnts.size() == n) break;
            if(mp[i] == 0) {
                cnts.push_back(i);
                mp[k - i] = 1;
            }
        }
        
        int res = 0;
        for(auto it: cnts) {
            res += it;
        }
        
        return res;
    }
};

 

 

 区间问题常见解法有动态规划,贪心, 双指针。本题采用动态规划来解

f[i]表示只从前0 - i中选,所获得的最大价值。

若不选第i个点 f[i] = f[i - 1];若选di第i个点,则第i个点一定是某个区间的右端点,向前遍历其左端点j, f[i] = max(f[i], f[j - 1] + w)

class Solution {
public:
    int maximizeTheProfit(int n, vector<vector<int>>& offers) {
        int m = offers.size();
        vector<int> f(n + 1);
        vector<vector<int>> g(n);
        for(int i = 0; i < m; i ++ ) {
            g[offers[i][1]].push_back(i); //右端点处记录该段所在位置
        }
        for(int i = 1; i <= n; i ++ ) {
             f[i] = f[i - 1];
             for(int j: g[i - 1]) {
                 f[i] = max(f[i], f[offers[j][0]] + offers[j][2]); //之前的左端点 + 当前区间价值
             }
        }
        return f[n];
    }
};

 

 

 可以有计数 + 二分、计数+双指针两种解法

计数用来快速查找出两个相邻元素中其他元素数量

方法一、计数+二分

二分枚举最长长度,

class Solution {
public:
    int longestEqualSubarray(vector<int>& nums, int k) {
        int n = nums.size(), l = 0, r = n + 1;
        unordered_map<int, vector<int>> mp;
        for(int i = 0; i < n; i ++ ) {
            mp[nums[i]].push_back(i);
        }

        auto check = [&](int len) -> bool {
            for(auto &[_, vec]: mp) {
                for(int i = 0; i + len - 1 < vec.size(); i ++ ) {
                    if(vec[i + len - 1] - vec[i] + 1 - len <= k)
                        return true;
                }
            }
            return false;
        };

        while(l + 1 < r) {
            int mid = l + r >> 1;
            if(check(mid)) l = mid;
            else r = mid;
        }

        return l;
    }
};

 

方法二:计数+双指针

class Solution {
public:
    int longestEqualSubarray(vector<int>& nums, int k) {
        int n = nums.size();
        vector<vector<int>> p(n + 1);
        for(int i = 0; i < n; i ++ ) {
            p[nums[i]].push_back(i);
        }

        int res = 0;
        for(int u = 1; u <= n; u ++ ) {
            auto &q = p[u];
            for(int i = 0, j = 0; i < q.size(); i ++ ) {
                while((q[i] - q[j]) - (i - j) > k) j ++ ; //q[i] - q[j] + 1 两个相同元素中间元素个数 i - j + 1两个相同元素中间和该元素相同的元素个数
                res = max(res, i - j + 1);
            }
        }

        return res;
    }
};

 

posted @ 2023-08-20 15:00  深渊之巅  阅读(24)  评论(0编辑  收藏  举报