力扣第354场周赛(题解)

 夜的钢琴曲五 - Leon不太冷 - 单曲 - 网易云音乐

力扣的核心代码模式还是不习惯,很多class类中面向对象知识的细节,一不注意,ACM模式能AC的,核心代码模式找不到问题。

(补充)STL真的很好用,不论是核心代码模式,还是ACM模式,熟练根据不同容器的不同特点使用,还有就是,牢记不同算法,很重要!

目录

特殊元素平方和

数组的最大美丽值

合法分割的最小下标

最长合法子字符串的长度

总结


特殊元素平方和

6889. 特殊元素平方和 - 力扣(LeetCode)

简单

坑,因为是传入的数组,默认下标 0 ~ n-1,所以for循环中不能 1 ~ n,会数组越界

AC  代码

class Solution {
public:
    int sumOfSquares(vector& nums) {
        int ans = 0, n = nums.size();
        for(int i = 0; i < n; ++i) { //注意数组越界
            if(n % (i+1) == 0)
                ans += nums[i] * nums[i];
        }
        return ans;
    }
};

数组的最大美丽值

6929. 数组的最大美丽值 - 力扣(LeetCode)

中等

1,注意vector中,排序用sort(),参数是迭代器,分别是起始位置和最后一个元素的下一位置的地址

2,坑,还是数组越界问题,while()循环中加个 j < nums.size()防止越界

3,采取双指针,滑窗的办法,只需要收集差值在 2*k 以内的最长区间

4,据说还可以二分,不过慢一点,得O(nlogn),而滑窗好像O(n)

AC  代码

class Solution {
public:
    int maximumBeauty(vector& nums, int k) {
        sort(nums.begin(), nums.end());
        int ans = 1;
        for(int i = 0, j = 0; i < nums.size(); ++i) {
            while(j < nums.size() && nums[j] - nums[i] <= 2*k) {
                ans = max(ans, j - i + 1);
                j++;
            }
            if(j >= nums.size()) break;
        }
        return ans;
    }
};

合法分割的最小下标

6927. 合法分割的最小下标 - 力扣(LeetCode)

中等 

1,本题直接采用multiset再用count统计元素个数,会超时

2,采取unordered_map,哈希表映射的方式,复杂度更低,而且重载了 [],可以直接通过[]访问对应键出现的次数

3,还是采取滑窗 + 哈希表(unorder_map)来统计

AC  代码

class Solution {
public:
    int minimumIndex(vector& nums) {
        unordered_map countMap; // 创建一个无序映射,用于记录每个数字出现的次数
        int len = 0, pos; //len表示当前出现最多次数的数字的出现次数,pos表示该数字最后一次出现的位置

        for (int i = 0; i < nums.size(); ++i) {
            countMap[nums[i]]++; //记录数字出现的次数
            if (len < countMap[nums[i]]) {
                len = countMap[nums[i]]; //更新最大出现次数
                pos = i;
            }
            if (len > nums.size() / 2 + 1) break; //剪枝
        }
        
        if (len <= nums.size() / 2) return -1; //最大出现次数 <= 数组长度一半
        
        int flag = 0;
        int ans, number = 0; //ans表示满足条件的位置,number表示当前数字出现的次数
        for (int i = 0; i < nums.size(); ++i) {
            if (nums[i] == nums[pos])
                number++;
            //左半部分和右半部分都要满足
            if (number > (i + 1) / 2 && len - number > (nums.size() - i - 1) / 2) {
                flag = 1;
                ans = i;
                break;
            }
        }
        
        if (flag) return ans;
        return -1;
    }
};

最长合法子字符串的长度

6924. 最长合法子字符串的长度 - 力扣(LeetCode)

困难

方法:字典树 or 线段树 or AC自动机 or 双指针

决定采取双指针(对撞指针 or 快慢指针)来搞定这题,先学点知识点

算法一招鲜——双指针问题 - 知乎 (zhihu.com)

fucking-algorithm/算法思维系列/双指针技巧.md at master · labuladong/fucking-algorithm (github.com)

思路

....比赛时只用了暴力滑窗,如果当时结合unorder_map应该压线2*10^7过

(O(n + m) * L^2)

n为给定字符串长度1e5,m为forbidden字符串数量1e5,L为forbidden里最长字符串长度10

Wa723 / 761)时间超限

class Solution {
public:
    int longestValidSubstring(string word, vector& forbidden) {
        int ans = 0;
        for(int j = 0, i = 0; j < word.size(); ++j) { //枚举右端点 j
            string s = word.substr(i, j - i + 1); //第2个参数是长度
            for(int k = 0; k < forbidden.size(); ++k) {
                if(s.find(forbidden[k]) != string::npos) //发现包含
                    i++; //左端点 i 右移
                s = word.substr(i, j - i + 1); //第2个参数是长度
            }
            ans = max(ans, j - i + 1);
        }
        return ans;
    }
};

总结

1,熟练掌握STL常用容器及其对应特点(适用场景)

2,熟练使用STL容器相关算法

3,核心代码模式,注意数组超限问题;记得return

4,加强面向对象的学习

这是我的第10场比赛,希望大学剩下3年,能打满100场比赛,也不多。

等《算法训练营入门篇》和Acw蓝桥杯辅导课视频,学完,就可以开始养生刷题和打比赛了(每10天1场比赛,每天1道题)

先把基础算法学完,

不然就像这次这样,最后一题好像考到了KMP和双指针,KMP不会,双指针不熟,直接用substr和.find() == string::npos,超时了(大概 734/756),就算OI模式,最多给你30%的分。

你可能感兴趣的:(leetcode,算法,职场和发展,数据结构)