LeetCode第389场周赛个人题解

2024-03-17 21:44

本文主要是介绍LeetCode第389场周赛个人题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

100248. 字符串及其反转中是否存在同一子字符串

原题链接

思路分析

AC代码

100236. 统计以给定字符开头和结尾的子字符串总数

原题链接

思路分析

AC代码

100255. 成为 K 特殊字符串需要删除的最少字符数

原题链接

思路分析

AC代码

100227. 拾起 K 个 1 需要的最少行动次数

原题链接

思路分析

AC代码


100248. 字符串及其反转中是否存在同一子字符串

原题链接





100248. 字符串及其反转中是否存在同一子字符串

思路分析

签到题,直接模拟

AC代码

class Solution:def isSubstringPresent(self, s: str) -> bool:return any(s[i:i+2] in s[::-1] for i in range(len(s) - 1))

100236. 统计以给定字符开头和结尾的子字符串总数

原题链接

100236. 统计以给定字符开头和结尾的子字符串总数

思路分析

简单递推

f[i]为前i个元素中以c开头c结尾的子字符串总数,cnt[i]为前i个元素中c的数目

有 f[i] = f[i - 1],s[i] != c时

f[i] = f[i - 1] + cnt[i - 1] + 1,s[i] != c时

时间复杂度:O(n)

AC代码

class Solution {
public:long long countSubstrings(string s, char c) {long long ret = 0, cnt = 0;for(auto x : s)if(x == c) ret = ret + cnt + 1, cnt++;return ret;}
};

100255. 成为 K 特殊字符串需要删除的最少字符数

原题链接

100255. 成为 K 特殊字符串需要删除的最少字符数

思路分析

滑动窗口

先统计词频,然后词频升序排序

然后一共就26个字符,枚举每个字符为左端的长度为k + 1的滑动窗口,计算对于每个窗口而言最少删除多少元素

时间复杂度:O(n)

AC代码

class Solution {
public:int minimumDeletions(string s, int k) {int cnt[26]{0}, pre[26]{0}, ret = 1e5, n = s.size();for(auto x : s) cnt[x - 'a']++;sort(cnt, cnt + 26);for(int i = 0; i < 26; i++) pre[i] = (i ? pre[i - 1] : 0) + cnt[i];if(cnt[25] - cnt[0] <= k) return 0;for(int i = 0, t; i < 26; i++){if(!cnt[i]) continue;auto p = lower_bound(cnt, cnt + 26, cnt[i] + k) - cnt;t = i ? pre[i - 1] : 0;for(; p < 26; p++) t += cnt[p] - cnt[i] - k;ret = min(ret, t);}return ret;}//a bb ccc ddddd
};







100227. 拾起 K 个 1 需要的最少行动次数

原题链接





思路分析

中位数贪心+二分

其实不用二分的,比赛的时候写红温了直接二分着来了(

1:我们考虑选取index后,对于相邻的1,可以一步得到

2:然后可以操作一以步数为2的代价造1并得到

3:对于其它的1,可以以其下标到index的距离的步数得到1

不难发现3的代价是大于1、2的

然后我们考虑如果1、2就能得到k个1,那就不考虑3了,因为代价会更大

如果要考虑3,那就等效于在剩余的1中挑出(k - maxChanges - 1中拿掉的1的个数)个1

然后要使得挑出来的1的下标到index距离和最小

那这一步是可以中位数贪心的

所以我们就枚举每个位置,然后先求1、2能拿的1,如果还要拿,就以index为中位数,去二分区间半径

如果区间内1的数目够了,就r = mid,否则l = mid + 1

然后求代价即可,这个可以前缀和预处理然后O(1)获得

然后有一个坑就是区间内的1的数目可能会多一个,所以如果多了要减去多出来的代价

时间复杂度O(nlogn)

可优化之处:

上面我们枚举中位数的过程中枚举了很多为0的位置,其实没必要,所以我们可以提前得到所有1的下标数组,然后在下标数组上枚举中位数,这样可以O(n)解决,而且不用二分

AC代码

class Solution {
public:long long minimumMoves(vector<int>& nums, int k, int maxChanges) {int n = nums.size();vector<int> cnt(n);vector<long long> pre(n);auto getcnt = [&](int i)->long long{if(i < 0) return 0;if(i >= n) return cnt[n - 1];return cnt[i];};auto getpre = [&](int i)->long long{if(i < 0) return 0;if(i >= n) return pre[n - 1];return pre[i];        };for(int i = 0; i < n; i++) cnt[i] = getcnt(i - 1) + nums[i], pre[i] = getpre(i - 1) + i * nums[i];long long ret = 1e12;for(int i = 0; i < n; i++){int res = k - nums[i];//indexlong long tot = 0;for(auto x : {-1, 1})//opt2if(res && i + x >= 0 && i + x < n) res -= nums[i + x], tot += nums[i + x];tot += min(maxChanges, res) * 2, res -= min(maxChanges, res);//opt1if(res){//二分int l = 1, r = n;while(l < r){int mid = l + r >> 1;if(getcnt(i - 2) - getcnt(i - mid - 1) + getcnt(i + mid) - getcnt(i + 1) >= res) r = mid;else l = mid + 1;}int lc = getcnt(i - 2) - getcnt(i - r - 1), rc = getcnt(i + r) - getcnt(i + 1);tot += getpre(i + r) - getpre(i + 1) - 1LL * rc * i + 1LL * lc * i - getpre(i - 2) + getpre(i - r - 1);tot -= (lc + rc - res) * r;}ret = min(ret, tot);}return ret;}
};

这篇关于LeetCode第389场周赛个人题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/820262

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

HomeBank:开源免费的个人财务管理软件

在个人财务管理领域,找到一个既免费又开源的解决方案并非易事。HomeBank&nbsp;正是这样一个项目,它不仅提供了强大的功能,还拥有一个活跃的社区,不断推动其发展和完善。 开源免费:HomeBank 是一个完全开源的项目,用户可以自由地使用、修改和分发。用户友好的界面:提供直观的图形用户界面,使得非技术用户也能轻松上手。数据导入支持:支持从 Quicken、Microsoft Money

【JavaScript】LeetCode:16-20

文章目录 16 无重复字符的最长字串17 找到字符串中所有字母异位词18 和为K的子数组19 滑动窗口最大值20 最小覆盖字串 16 无重复字符的最长字串 滑动窗口 + 哈希表这里用哈希集合Set()实现。左指针i,右指针j,从头遍历数组,若j指针指向的元素不在set中,则加入该元素,否则更新结果res,删除集合中i指针指向的元素,进入下一轮循环。 /*** @param

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

分布式系统的个人理解小结

分布式系统:分的微小服务,以小而独立的业务为单位,形成子系统。 然后分布式系统中需要有统一的调用,形成大的聚合服务。 同时,微服务群,需要有交流(通讯,注册中心,同步,异步),有管理(监控,调度)。 对外服务,需要有控制的对外开发,安全网关。