leetcode第161场周赛总结

leetcode第161场周赛总结

第一题:5247. 交换字符使得字符串相同

有两个长度相同的字符串 s1 和 s2,且它们其中 只含有 字符 “x” 和 “y”,你需要通过「交换字符」的方式使这两个字符串相同。
每次「交换字符」的时候,你都可以在两个字符串中各选一个字符进行交换。
交换只能发生在两个不同的字符串之间,绝对不能发生在同一个字符串内部。也就是说,我们可以交换 s1[i] 和 s2[j],但不能交换 s1[i] 和 s1[j]。
最后,请你返回使 s1 和 s2 相同的最小交换次数,如果没有方法能够使得这两个字符串相同,则返回 -1 。

示例1:

输入:s1 = “xx”, s2 = “yy”
输出:1
解释:
交换 s1[0] 和 s2[1],得到 s1 = “yx”,s2 = “yx”。

示例2:

输入:s1 = “xy”, s2 = “yx”
输出:2
解释:
交换 s1[0] 和 s2[0],得到 s1 = “yy”,s2 = “xx” 。
交换 s1[0] 和 s2[1],得到 s1 = “xy”,s2 = “xy” 。
注意,你不能交换 s1[0] 和 s1[1] 使得 s1 变成 “yx”,因为我们只能交换属于两个不同字符串的字符。

示例3:

输入:s1 = “xx”, s2 = “xy”
输出:-1

实例4:

输入:s1 = “xxyyxyxyxx”, s2 = “xyyxyxxxyx”
输出:4

提示:

1 <= s1.length, s2.length <= 1000
s1, s2 只包含 ‘x’ 或 ‘y’。

分析:
1、首先考虑哪种情况是如何交换都不可能使两个字符串相等的,只有这两个字符串中所有x和y的个数加起来都是偶数才能通过交换使两个字符串相等,否则无论如何交换都不可能使两个字符串相等。
2、对于两个字符串中相同位置的字符,如果已经相等了的话,则可以不用考虑它们,我们只需考虑那些同样位置不相等的字符。同样位置字符不相等一共只有两种可能,一是s1中这个字符是x,s2中这个字符是y,二是s1中这个字符是y,s2中这个字符是x。我们考虑这种情况,s1[i]=‘x’,s1[j]=‘x’,s2[i]=‘y’,s2[j]=‘y’,这种情况类似于示例1,只需通过一次交换即可使s1和s2的i,j位置的字符都相同。同理,对于s1[i]=‘y’,s1[j]=‘y’,s2[i]=‘x’,s2[j]='x’这种情况也是只需一次交换即可。考虑另一种情况,即s1[i]=‘x’,s1[j]=‘y’,s2[i]=‘y’,s2[j]=‘x’,这种情况类似于示例2,需要通过两次交换才能使s1和s2的i,j位置的字符都相同。同理,对于s1[i]=‘y’,s1[j]=‘x’,s2[i]=‘x’,s2[j]='y’这种情况也是需要两次交换。所以,我们只需统计需要交换一次和需要交换两次的这些情况各有多少种,即可算出答案。
代码如下:

class Solution:
    def minimumSwap(self, s1: str, s2: str) -> int:
        dic1 = collections.Counter(s1)
        dic2 = collections.Counter(s2)
        ans = 0
        if (dic1['x'] + dic2['x']) % 2 == 0 and (dic1['y'] + dic2['y']) % 2 == 0:
            dic = collections.defaultdict(int)
            for i in range(len(s1)):
                if s1[i] == s2[i]:
                    continue
                else:
                    dic[(s1[i], s2[i])] += 1
            if dic[('x', 'y')]:
                ans += dic[('x', 'y')] // 2
                dic[('x', 'y')] %= 2
            if dic[('y', 'x')]:
                ans += dic[('y', 'x')] // 2
                dic[('y', 'x')] %= 2
            if dic[('y', 'x')]:
                ans += dic[('y', 'x')] * 2
            return ans
        else:
            return -1
第二题:5248. 统计「优美子数组」

给你一个整数数组 nums 和一个整数 k。
如果某个子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。
请返回这个数组中「优美子数组」的数目。

示例1:

输入:nums = [1,1,2,1,1], k = 3
输出:2
解释:包含 3 个奇数的子数组是 [1,1,2,1] 和 [1,2,1,1] 。

示例2:

输入:nums = [2,4,6], k = 1
输出:0
解释:数列中不包含任何奇数,所以不存在优美子数组。

示例3:

输入:nums = [2,2,2,1,2,2,1,2,2,2], k = 2
输出:16

提示:

1 <= nums.length <= 50000
1 <= nums[i] <= 10^5
1 <= k <= nums.length

分析:
这题我一开始的想法是用滑动窗口去做,但是写起来发现,好多情况是不适合用滑动窗口去考虑的,比如我现在的窗口内已经包含了k哥奇数了,这个时候如果窗口右边界之后还有偶数的话,右边界可以继续向后滑动,而如果这时候窗口左边界之后也有偶数的话,那窗口的左边界也可以继续向后滑动。这种情况下,窗口左右边界可以同时滑动,那么就不太好统计优美子数组的个数了。所以,受此启发,我想到了可以去找出数组中所有奇数的位置,然后考虑以每个奇数作为优美子数组中的第一个奇数,这样也就能根据k确定优美子数组中的最后一个奇数是谁,然后包含这k个奇数的优美子数组的个数就=(这个优美子数组的第一个奇数的下标-它前一个奇数的下标)×(这个优美子数组的最后一个奇数的下标-它后一个奇数的下标)。
代码如下:

class Solution:
    def numberOfSubarrays(self, nums: List[int], k: int) -> int:
        ans = 0
        cnt = 0
        mem = [-1]
        for i, num in enumerate(nums):
            if num % 2 == 1:
                cnt += 1
                mem.append(i)
        mem.append(len(nums))
        for i in range(1, len(mem)-k):
            ans += (mem[i] - mem[i-1]) * (mem[i+k] - mem[i+k-1])
        return ans
第三题:5249. 移除无效的括号

给你一个由 ‘(’、’)’ 和小写字母组成的字符串 s。
你需要从字符串中删除最少数目的 ‘(’ 或者 ‘)’ (可以删除任意位置的括号),使得剩下的「括号字符串」有效。
请返回任意一个合法字符串。
有效「括号字符串」应当符合以下 任意一条 要求:
空字符串或只包含小写字母的字符串
可以被写作 AB(A 连接 B)的字符串,其中 A 和 B 都是有效「括号字符串」
可以被写作 (A) 的字符串,其中 A 是一个有效的「括号字符串」

示例1:

输入:s = “lee(t©o)de)”
输出:“lee(t©o)de”
解释:“lee(t(co)de)” , “lee(t©ode)” 也是一个可行答案。

示例2:

输入:s = “a)b©d”
输出:“ab©d”

示例3:

输入:s = “))((”
输出:""
解释:空字符串也是有效的

示例4:

输入:s = “(a(b©d)”
输出:“a(b©d)”

提示:

1 <= s.length <= 10^5
s[i] 可能是 ‘(’、’)’ 或英文小写字母

分析:
使用栈来找出不匹配的括号。
代码如下:

class Solution:
    def minRemoveToMakeValid(self, s: str) -> str:
        mem = [0] * len(s)
        stack = []
        ans = ""
        for i, c in enumerate(s):
            if c not in ['(', ')']:
                mem[i] = 1
            else:
                if c == '(':
                    stack.append([c, i])
                else:
                    if not stack:
                        continue
                    else:
                        mem[stack[-1][1]] = 1
                        mem[i] = 1
                        stack.pop()
        for i in range(len(mem)):
            if mem[i] == 1:
                ans += s[i]
        return ans

第四题:5250. 检查「好数组」

给你一个正整数数组 nums,你需要从中任选一些子集,然后将子集中每一个数乘以一个 任意整数,并求出他们的和。
假如该和结果为 1,那么原数组就是一个「好数组」,则返回 True;否则请返回 False。

示例1:

输入:nums = [12,5,7,23]
输出:true
解释:挑选数字 5 和 7。
53 + 7(-2) = 1

示例2:

输入:nums = [29,6,10]
输出:true
解释:挑选数字 29, 6 和 10。
291 + 6(-3) + 10*(-1) = 1

示例3:

输入:nums = [3,6]
输出:false

提示:

1 <= nums.length <= 10^5
1 <= nums[i] <= 10^9

分析:
题目说可以任选一些子集,然后然后将子集中每一个数乘以一个 任意整数,并求出他们的和,假如该和结果为 1,那么原数组就是一个「好数组」。那么假设我挑两个数x和y,选择他们要×的参数为a和b,计算他们的和即(ax+by),现在假如x和y的最大公约数为1,那么(ax+by)可以写成1×(ax+by),只需要选择合适的a和b使ax+by=1即可。而如果x和y的最大公约数为1不为1,就假设为2吧,那么(ax+by)可以写成2×(ax’+by’),因为x和y都是正整数,而a,b是任意整数,所以(ax’+by’)的结果肯定是个整数,所以2×(ax’+by’)肯定是2的倍数,就不可能是1。所以只要能找出最大公约数是1的子集就能满足条件,否则就不能。
代码如下:

class Solution:
    def isGoodArray(self, nums: List[int]) -> bool:
        g = nums[0]
        if len(nums) == 1 and g == 1:
            return True
        for num in nums[1:]:
            g = math.gcd(num, g)
            if g == 1:
                return True
        return False
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本项目是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。该系统主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者,包含项目源码、数据库脚本、项目说明等,有论文参考,可以直接作为毕设使用。 后台框架采用SpringBoot,数据库使用MySQL,开发环境为JDK、IDEA、Tomcat。项目经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。 该系统的功能主要包括商品管理、订单管理、用户管理等模块。在商品管理模块中,可以添加、修改、删除商品信息;在订单管理模块中,可以查看订单详情、处理订单状态;在用户管理模块中,可以注册、登录、修改个人信息等。此外,系统还提供了数据统计功能,可以对销售数据进行统计和分析。 技术实现方面,前端采用Vue框架进行开发,后端使用SpringBoot框架搭建服务端应用。数据库采用MySQL进行数据存储和管理。整个系统通过前后端分离的方式实现,提高了系统的可维护性和可扩展性。同时,系统还采用了一些流行的技术和工具,如MyBatis、JPA等进行数据访问和操作,以及Maven进行项目管理和构建。 总之,本系统是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。系统经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值