【LeetCode周赛】第 390 场周赛

3090. 每个字符最多出现两次的最长子字符串 简单

3090. 每个字符最多出现两次的最长子字符串

分析:
数据量,按照题意模拟即可。
这里我是用了 前缀和 记录了 0~i 的所有字母出现的次数。

代码:

C++

class Solution {
public:
    int maximumLengthSubstring(string s) {
        int n=s.length();
        vector<vector<int>> cnt(n+1,vector<int>(26,0));
        for(int i=0;i<n;i++){
            cnt[i+1][s[i]-'a']++;
            for(int j=0;j<26;j++) cnt[i+1][j]+=cnt[i][j];
        }
        for(int i=n;i>1;i--){
            for(int j=0;j+i<=n;j++){
                int k=0;
                for(;k<26;k++){
                    if(cnt[j+i][k]-cnt[j][k]>2) break;
                }
                if(k==26) return i;
            }
        }
        return 1;
    }
};

python

class Solution:
    def maximumLengthSubstring(self, s: str) -> int:
        cnt = [[0] * 216 for i in range(len(s)+1)]
        for i in range(len(s)):
            cnt[i+1][ord(s[i]) - ord('a')]+=1
            for j in range(26):
                cnt[i+1][j] += cnt[i][j]

        for i in range(len(s),1,-1):
            for j in range(0,len(s)-i+1):
                flag = True
                for k in range(26):
                    if cnt[i+j][k] - cnt[j][k]>2:
                        flag=False
                        break
                if flag:
                    return i
        return 1


3091. 执行操作使数据元素之和大于等于 K 中等

3091. 执行操作使数据元素之和大于等于 K

分析:

法一
贪心+找规律
在固定的操作次数 l l l 下,先进行 ⌊ l / 2 ⌋ \lfloor l/2 \rfloor l/2 次操作一,再进行 l − ⌊ l / 2 ⌋ l - \lfloor l/2 \rfloor ll/2 操作二,即可得到最大的元素之和。
规律如下:

操作次数 l 最大元素之和
1 1 1 1 ∗ 2 = 2 1 * 2 = 2 12=2
2 2 2 2 ∗ 2 = 4 2 * 2 = 4 22=4
3 3 3 2 ∗ 3 = 6 2 * 3 = 6 23=6
4 4 4 3 ∗ 3 = 9 3 * 3 = 9 33=9
5 5 5 3 ∗ 4 = 12 3 * 4 = 12 34=12
6 6 6 4 ∗ 4 = 16 4 * 4 = 16 44=16

最终依照此规律,寻找最小的大于 k 的操作次数。

法二
贪心+枚举
先加,后复制得到的数更大。
最多进行 k-1 次加法,此时是操作次数最大的情况,枚举 1~k-1 次加法,再计算后续还需要多少次复制,维护最小操作数即可。

代码:

法一
C++

class Solution {
public:
    int minOperations(int k) {
        if(k==0||k==1) return 0;
        int cnt=1,a=1,b=2;
        while(a*b<k){
            if(a<b) a++;
            else b++;
            cnt++;
        }
        return cnt;
    }
};

python

class Solution:
    def minOperations(self, k: int) -> int:
        if k==1 or k==0:
            return 0
        cnt,a,b=1,1,2
        while a*b<k:
            if a<b:
                a+=1
            else:
                b+=1
            cnt+=1
        return cnt

法二法二

3092. 最高频率的 ID 中等

3092. 最高频率的 ID

分析:
寻找每次操作后,出现频率最高的数即可。
题目难点在于,在每次操作之后怎么寻找当前出现频率最高的数。

  • 遍历的话,数据量大一定超时。
  • 利用语言自带的工具
    • 哈希表 + 可重复的有序集合:c++中的 multiset ,python中的 SortedList
    • 哈希表 + 优先队列 + 懒删除堆

懒删除堆:因为优先队列不能查找,因此对于并非队首或队尾的元素,我们无法操作。可以使用 哈希表 维护当前的ID出现的次数,并将修改后的ID即其出现次数放入优先队列。同时对比优先队列队首的ID出现次数,与当前不符,就弹出。

代码:

哈希表 + 可重复的有序集合
C++

class Solution {
public:
    vector<long long> mostFrequentIDs(vector<int>& nums, vector<int>& freq) {
        unordered_map<int ,long long> m;
        multiset<long long> s;
        vector<long long> ans;
        m[nums[0]]+=1LL*freq[0];
        s.emplace(1LL*freq[0]);
        ans.push_back(1LL*freq[0]);
        for(int i=1;i<nums.size();i++){
            long long t = m[nums[i]];
            m[nums[i]]+=1LL*freq[i];
            auto it = s.find(t);
            if(it != s.end()){
                s.erase(it); // 删除集合中的一个 t
            }
            s.insert(m[nums[i]]);
            ans.push_back(*s.rbegin()); // 有序集合,s.rbegin() 即为最大的出现次数
        }
        return ans;
    }
};

python

from sortedcontainers import SortedList
class Solution:
    def mostFrequentIDs(self, nums: List[int], freq: List[int]) -> List[int]:
        cnt = Counter()
        s = SortedList()
        ans = []
        for x,f in zip(nums, freq):
            t = cnt[x]
            s.discard(t)
            cnt[x]+=f
            s.add(cnt[x])
            ans.append(s[-1])
        return ans

哈希表 + 优先队列 + 懒删除堆
C++

class Solution {
public:
    vector<long long> mostFrequentIDs(vector<int>& nums, vector<int>& freq) {
        unordered_map<int ,long long> m;
        priority_queue<pair<long long, int>> q;
        vector<long long> ans;
        m[nums[0]]+=1LL*freq[0];
        q.emplace(m[nums[0]], nums[0]);
        ans.push_back(1LL*freq[0]);
        for(int i=1;i<nums.size();i++){
            long long t = m[nums[i]];
            m[nums[i]]+=1LL*freq[i];
            q.emplace(m[nums[i]], nums[i]); // 不断的将修改后的 ID 及其 对应的出现次数 加入优先队列
            // 如下循环 实现 懒删除堆
            while(m[q.top().second] != q.top().first) q.pop(); // 与当前 ID 的出现次数不符合,弹出优先队列
            ans.push_back(q.top().first);
        }
        return ans;
    }
};

python

class Solution:
    def mostFrequentIDs(self, nums: List[int], freq: List[int]) -> List[int]:
        cnt = Counter()
        h = []
        ans = []
        for x,f in zip(nums, freq):
            cnt[x]+=f
            heapq.heappush(h, (-cnt[x], x))
            while -h[0][0] != cnt[h[0][1]]:
                heapq.heappop(h)
            ans.append(-h[0][0])
        return ans


3093. 最长公共后缀查询 困难

3093. 最长公共后缀查询

分析:
构建基于字符串后缀的字典树,并且不断维护对应下标,后续不断在字典树上查找即可。
注意数组的使用,容易内存超限。
同时注意当没有后缀与其匹配是,需要填入最短字符串的下标、

构建字典树模板:CPP
构建字典树模板:Python

代码:

C++

class Node{
public:
    int index=-1;
    Node* next[26]{};
};

class Solution {
public:
    vector<int> stringIndices(vector<string>& wordsContainer, vector<string>& wordsQuery) {
        int n=wordsContainer.size(),m=wordsQuery.size(),d=1e4+5,dindex=-1;
        vector<int> ans;
        Node* root = new Node();
        for(int i=0;i<n;i++){
            int l=wordsContainer[i].length();
            if(d>l) d=l,dindex=i;
            Node* node = root;
            for(int j=l-1;j>=0;j--){
                int k = wordsContainer[i][j]-'a';
                if(!node->next[k]) node->next[k] = new Node();
                node = node->next[k];
                if(node->index==-1) node->index=i;
                else{
                    if(wordsContainer[node->index].length()>l) node->index=i;
                }
            }
        }
        for(int i=0;i<m;i++){
            Node* node = root;
            int l=wordsQuery[i].length();
            int index=-1;
            for(int j=l-1;j>=0;j--){
                int k = wordsQuery[i][j]-'a';
                if(!node->next[k])break;
                node=node->next[k];
                index=node->index;
            }
            ans.push_back(index!=-1?index:dindex);
        }
        return ans;
    }
};

python

class Node:
    def __init__(self) -> None:
        self.children = [None] * 26
        self.index = -1

class Solution:
    def stringIndices(self, wordsContainer: List[str], wordsQuery: List[str]) -> List[int]:
        n,m = len(wordsContainer), len(wordsQuery)
        d,d_index = len(wordsContainer[0]),0
        ans = []
        def build_trie() -> Node: # 构建字典树
            nonlocal wordsContainer,d,d_index
            root = Node()
            for i in range(n):
                l=len(wordsContainer[i])
                if d>l:
                    d=l
                    d_index=i
                node = root
                for j in range(l-1, -1, -1):
                    k = ord(wordsContainer[i][j]) - ord('a') # 字母转换成下标
                    if node.children[k] == None:
                        node.children[k] = Node()
                    node = node.children[k]
                    if node.index == -1: # 更新更优下标
                        node.index = i
                    else:
                        node.index = i if len(wordsContainer[node.index]) > l else node.index
            return root
        root = build_trie()
        def find_word(s: str):
            nonlocal root
            node = root
            index = -1
            for i in range(len(s)-1,-1,-1):
                k = ord(s[i]) - ord('a')
                if node.children[k]==None:
                    break
                node = node.children[k]
                index = node.index
            return index
        for i in range(m):
            t = find_word(wordsQuery[i])
            ans.append(t if t!=-1 else d_index)
        return ans

相关推荐

  1. LeetCode 390

    2024-03-26 17:28:01       41 阅读
  2. LeetCode 392

    2024-03-26 17:28:01       36 阅读
  3. LeetCode 394

    2024-03-26 17:28:01       31 阅读
  4. LeetCode -- 392

    2024-03-26 17:28:01       37 阅读
  5. LeetCode 390个人题解

    2024-03-26 17:28:01       42 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-26 17:28:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-26 17:28:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-26 17:28:01       82 阅读
  4. Python语言-面向对象

    2024-03-26 17:28:01       91 阅读

热门阅读

  1. VC++ class wizard介绍

    2024-03-26 17:28:01       34 阅读
  2. 每日一题:C语言经典例题之字符串的比较

    2024-03-26 17:28:01       41 阅读
  3. 高斯数据库[GaussDB]TPDSS下面执行批量脚本报错。

    2024-03-26 17:28:01       36 阅读
  4. js高阶数组练习题

    2024-03-26 17:28:01       38 阅读
  5. python,pytorch进入虚拟环境(linux)

    2024-03-26 17:28:01       36 阅读
  6. 我与计算机

    2024-03-26 17:28:01       36 阅读
  7. leetcode 518.零钱兑换 II

    2024-03-26 17:28:01       35 阅读