首页 > 其他分享 >leetcode第390场周赛

leetcode第390场周赛

时间:2025-01-16 22:35:53浏览次数:1  
标签:周赛 cnt vector int tr 390 ans leetcode size

目录

leetcode 第 390 场周赛

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

题意

给定一个长度小于等于 100 的仅由小写字母构成的字符串,请你找一个最长的子串,满足其中每种字符最多出现两次

思路

考虑到数据范围,可以直接暴力判断所有可能的字串是否满足题意,记录过程中的最大值即可。

时间复杂度 \(O(n^2)\)

看到本题的第一眼就是双指针的思路。定义一前一后两个指针,前指针一直向前,统计途中的字符出现次数,直到出现次数大于 2 的字符为止,此时后指针往前跑直至该字符的出现次数小于等于 2 为止;前指针再次出发,重复上述行为;过程中记录下满足题意的最大值即可。

时间复杂度 \(O(n)\)

代码

class Solution {
public:
    int maximumLengthSubstring(string s) {
        int ans = 1;
        int l = 0, r = 0, n = s.size();
        vector<int> cnt(26);
        while(r < n){
            ++ cnt[s[r] - 'a'];
            if(cnt[s[r] - 'a'] > 2){
                while(l < r && cnt[s[r] - 'a'] > 2){
                    -- cnt[s[l] - 'a'];
                    ++ l;
                }
            }else{
                ans = max(ans, r - l + 1);
            }
            ++ r;
        }
        return ans;
    }
};

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

题意

给定一个整数 k,你拥有一个初始数组,里面只有数字 1。

你可以执行两种操作:

  • 选择一个数组里面的元素,使其 + 1

  • 选择一个数组里面的元素,在当前数组中再添加一个该元素

问最终数组元素之和大于等于 k 所需的最少操作次数?

思路

可以考虑到,如果说最终的操作需要若干次 + 1 操作和复制操作,那么 + 1 操作一定出现在复制操作之前

所以我们优先 + 1 操作,再利用其进行复制操作。

考虑到 \(1 \le k \le 10^5\),所以可以枚举 + 1 的次数,过程中取最小的总操作次数即可

代码

class Solution {
public:
    int minOperations(int k) {
        const int inf = 0x3f3f3f3f;
        int ans = inf;
        for(int i = 1; i <= k; ++ i){
            ans = min(ans, (i - 1) + (k + i - 1) / i - 1);
        }
        return ans;
    }
};

100258. 最高频率的 ID

题意

给定两个长度均为 n 的数组 numsfreqfreq 数组中的数表示:初始集合为空,对于数组 freq 中的第 i 个数 freq[i],将会在该集合中添加 freq[i] 个数 nums[i]freq[i] < 0 时代表删除数)

要求你返回一个长度为 n 的数组,标识每一次操作后,当前集合中出现频率最高的元素的数目

\(1 \le n 、nums[i] \le 10^5,-10^5 \le freq[i] \le 10^5\)

思路

看到 1e5 范围的统计频率,联想到单点修改,区间查询最大值的线段树

也可以利用 multiset 来动态维护频率最大值

代码

  • 线段树
#define ll long long
struct Segment_Tree{//update - range_add + query - range_max
	int n;
	vector<ll> seg, tag, val;
	Segment_Tree(int cnt) : n(cnt), seg(cnt << 2, 0), tag(cnt << 2, 0), val(cnt + 1, 0){}
	int ls(int p) { return p << 1; }
	int rs(int p) { return p << 1 | 1; }

	void push_up(int p){ seg[p] = max(seg[ls(p)], seg[rs(p)]); return ;	}
	void build(int p, int pl, int pr){
		tag[p] = 0;
		if(pl == pr){
			seg[p] = val[pl]; return ;
		}
		int mid = pl + pr >> 1;
		build(ls(p), pl, mid);
		build(rs(p), mid + 1, pr);
		push_up(p);
		return ;
	}

	void addtag(int p, int pl, int pr, ll k){
		tag[p] += k;
		seg[p] += (pr - pl + 1) * k;
		return ;
	}

	void push_down(int p, int pl, int pr){
		if(tag[p]){
			int mid = pl + pr >> 1;
			addtag(ls(p), pl, mid, tag[p]);
			addtag(rs(p), mid + 1, pr, tag[p]);
			tag[p] = 0;
		}
		return ;
	}

	void update(int p, int pl, int pr, int l, int r, ll k){
		if(l <= pl && pr <= r){
			addtag(p, pl, pr, k);
			return ;
		}
		push_down(p, pl, pr);
		int mid = pl + pr >> 1;
		if(l <= mid) update(ls(p), pl, mid, l, r, k);
		if(mid < r) update(rs(p), mid + 1, pr, l, r, k);
		push_up(p);
		return ;
	}

	ll query(int p, int pl, int pr, int l, int r){
		if(l <= pl && pr <= r){
			return seg[p];
		}
		push_down(p, pl, pr);
		ll res = 0;
		int mid = pl + pr >> 1;
		if(l <= mid) res = max(res, query(ls(p), pl, mid, l, r));
		if(mid < r) res = max(res, query(rs(p), mid + 1, pr, l, r));
		return res;
	}
};

class Solution {
public:
    vector<long long> mostFrequentIDs(vector<int>& a, vector<int>& q) {
        int n = q.size(), mx = 1e5;
        vector<long long> ans(n);
        Segment_Tree tree(mx);
        for(int i = 0; i < n; ++ i){
            tree.update(1, 1, mx, a[i], a[i], q[i]);
            ans[i] = tree.query(1, 1, mx, 1, mx);
        }
        return ans;
    }
};
  • multiset
class Solution {
public:
    vector<long long> mostFrequentIDs(vector<int>& a, vector<int>& q) {
        int n = a.size();
        vector<long long> ans(n);
        multiset<long long> f;
        map<int, long long> cnt;
        for(int i = 0; i < n; ++ i){
            if(cnt[a[i]])
                f.erase(f.find(cnt[a[i]]));
            cnt[a[i]] += q[i];
            f.insert(cnt[a[i]]);
            if(f.size()) ans[i] = *f.rbegin();
        }
        return ans;
    }
};

100268. 最长公共后缀查询

题意

给定一组字符串和一组字符串询问,对于每一个询问的字符串,在给定的字符串中找到一个与询问字符串有最长公共后缀的字符串,如果有多个满足题意得则优先找长度短的、下标小的

给定字符串的总长度和询问字符串的总长度均小于 5e5,字符串个数均小于 1e4

思路

Trie树插入和查询

对于树上的每一个节点都打上两个标记:id 和 len,id 记录当前节点标记的后缀所对应的匹配的字符串的下标,len 即为该字符串的长度。如此,在插入字符串时维护这两个标记即可

代码

struct Trie{
    // using ll = long long;
    enum {alpha = 26, st = 'a'};
    struct node{
        int id = 0, len = INT_MAX;// 保存id
        int ch[alpha] = {0};
        node(){}
    };
    vector<node> tr;
    int new_node(){
        tr.emplace_back();
        return tr.size() - 1;
    }
    Trie(){ new_node(); }

    void judge(int x, int y, int size){
        if(size < tr[x].len || size == tr[x].len && y < tr[x].id){
            tr[x].len = size;
            tr[x].id = y;
        }
        return ;
    }

    void insert(const string & ss, int id, int size){
        int p = 0;// 根节点
        for(int i = ss.size() - 1; i >= 0; -- i){
            char c = ss[i];
            if(!tr[p].ch[c - st])
                tr[p].ch[c - st] = new_node();
            judge(p, id, size);
            p = tr[p].ch[c - st];
        }
        judge(p, id, size);
        return ;
    }

    int find(const string & ss){
        int p = 0;
        for(int i = ss.size() - 1; i >= 0; -- i){
            char c = ss[i];
            if(!tr[p].ch[c - st]) return tr[p].id;
            p = tr[p].ch[c - st];
        }
        return tr[p].id;
    }
};

class Solution {
public:
    vector<int> stringIndices(vector<string>& ss, vector<string>& q) {
        Trie tree;
        for(int i = 0; i < ss.size(); ++ i){
            tree.insert(ss[i], i, ss[i].size());
        }
        vector<int> ans;
        for(auto& s : q){
            ans.push_back(tree.find(s));
        }
        return ans;
    }
};

标签:周赛,cnt,vector,int,tr,390,ans,leetcode,size
From: https://www.cnblogs.com/Qiansui/p/18675855

相关文章

  • LeetCode | 图文详细描述动态规划DP算法及经典题型
    本文将用简单直白的方式,从零开始带你掌握动态规划的精髓。你会发现:动态规划其实没那么难——它就是递归的“记性”版。状态转移方程不再玄学——从题目思路到实现,手把手教你推导。经典题型剖析——从“爬楼梯”到“背包问题”,全都有图、有代码、有思路。看完这篇文章,动态规划......
  • LeetCode:100.相同的树
    LeetCode:100.相同的树两个树:根节点的值相同,左子树相同,右子树相同。符合“分、解、合”特性。考虑选择分而治之。分:获取两个树的左子树和右子树。解:递归地判断两个树的左子树是否相同,右子树是否相同。合:将上述结果合并,如果根节点的值也相同,树就相同。/***Definitionforab......
  • 【LeetCode 刷题】数组-模拟-螺旋矩阵
    此博客为《代码随想录》数组章节的学习笔记,主要内容为数组模拟的相关题目解析。文章目录59.螺旋矩阵II54.螺旋矩阵59.螺旋矩阵II题目链接classSolution:defgenerateMatrix(self,n:int)->List[List[int]]:l,r,t,b=0,n-1,0,n-......
  • 【LeetCode 刷题】数组-滑动窗口
    此博客为《代码随想录》数组章节的学习笔记,主要内容为滑动窗口知识点的相关题目解析。文章目录209.长度最小的子数组904.水果成篮76.最小覆盖子串209.长度最小的子数组题目链接classSolution:defminSubArrayLen(self,target:int,nums:List[int])->......
  • LeetCode 1773. 统计匹配检索规则的物品数量
    在这个问题中,我们被要求统计一个物品数组中满足特定检索规则的物品数量。每个物品由其类型、颜色和名称定义,而检索规则由规则键和规则值指定。我们的任务是找出数组中满足这些规则的物品数量。问题描述解题思路定义索引映射:首先,我们需要定义一个映射,将规则键("type"、"color......
  • LeetCode字符串
    LeetCode字符串LeetCode字符串刷题记录基础知识字符串和数组很相似每个元素的数据类型相同都可以通过下标索引访问字符串比大小从第0个位置开始,依次比较对应位置上的字符编码大小defcompare(str1,str2):i=0j=0whilei<len(str1)andj<len(s......
  • LeetCode题练习与总结:省份数量--547
    一、题目描述有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。给你一个 nxn 的矩阵 isConnected ,其......
  • LeetCode题练习与总结:游戏玩法分析 Ⅳ -- 550
    一、题目描述SQLSchema> PandasSchema> Table: Activity+--------------+---------+|ColumnName|Type|+--------------+---------+|player_id|int||device_id|int||event_date|date||games_played|int|+----......
  • LeetCode题练习与总结:移除盒子--546
    一、题目描述给出一些不同颜色的盒子 boxes ,盒子的颜色由不同的正数表示。你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 k 个盒子(k >=1),这样一轮之后你将得到 k*k 个积分。返回 你能获得的最大积分和 。示例1:......
  • LeetCode:21.合并两个有序链表
    LeetCode:21.合并两个有序链表解题思路与归并排序中的合并两个有序数组很相似。将数组替换成链表就能解此题。解题步骤新建一个新链表,作为返回结果。用指针遍历两个有序链表,并比较两个链表的当前节点,较小者先接入新链表,并将指针后移一步。链表遍历结束,返回新链表。/***Defini......