[LeetCode周赛复盘] 第 321 场周赛20221127

本文是关于LeetCode第321场周赛的总结,详细解析了四道题目:找出中枢整数、追加字符以获得子序列、从链表中移除节点以及统计中位数为K的子数组。通过思路分析和代码实现,展示了如何解决这些问题,涉及双指针、递归、前缀和等算法技巧。
摘要由CSDN通过智能技术生成

一、本周周赛总结

  • 好难啊,但是怎么过的人这么多。
  • T1暴力或者公式。
  • T2子序列双指针。
  • T3链表题。
  • T4前缀和+哈希表,两种做法。
    在这里插入图片描述

二、 [Easy] 6245. 找出中枢整数

链接: 6245. 找出中枢整数

1. 题目描述

在这里插入图片描述

2. 思路分析

按题意模拟即可。

3. 代码实现

class Solution:
    def pivotInteger(self, n: int) -> int:
        s = (1+n)*n//2
        p = 0
        for i in range(1,n+1):
            p += i
            if p == s - p + i:
                return i 
        return -1

三、[Medium]6246. 追加字符以获得子序列

链接: 6246. 追加字符以获得子序列

1. 题目描述

在这里插入图片描述

2. 思路分析

按题意模拟即可。

  • 和判断子序列很像,直接双指针扫描即可。
  • 看s最多能匹配t前缀多长。

3. 代码实现

class Solution:
    def appendCharacters(self, s: str, t: str) -> int:
        m,n = len(s),len(t)
        j = 0
        for i,c in enumerate(s):
            if j<n and t[j] == c:
                j += 1
            if j == n:
                return 0
        # print(n,j)
        return n - j

四、[Medium] 6247. 从链表中移除节点

链接: 6247. 从链表中移除节点

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 比赛时直接转数组然后dp做的,其实可以递归,下面给出递归写法。

3. 代码实现

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNodes(self, head: Optional[ListNode]) -> Optional[ListNode]:
        """最后的结果,head一定是最大的,且后缀同样满足这个属性,因此可以递归
        """
        if not head :return head 
        nxt = self.removeNodes(head.next)
        if not nxt:return head 
        if nxt.val > head.val :return nxt 
        head.next = nxt
        return head

五、[Hard] 6248. 统计中位数为 K 的子数组

链接: 6248. 统计中位数为 K 的子数组

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 比赛时写了比较麻烦的左右前缀和,还wa一次。
  • 注意题目,数据是1-n的排列。意味着k一定只出现一次。找到k的位置p。所有子数组都要包含p。
  • k如果是中位数的话,这个数组里小于k的数less一定等于大于k的数big,或less+1=big(偶数长度情况)
  • 于是我们从p出发向两侧扩展数组,使用前缀和统计两边子数组less和big的大小计数。
  • 于是就可以用乘法原理乘起来即可。

  • 更简单的方法可以转换,把原数组转化为:小于k记-1,大于k记1,等于k记10**6。
  • 题目转化成有多少个子数组,子数组和=106或106+1。
  • 这题就是普通的前缀和+哈希表。

3. 代码实现

转化为前缀和+哈希表

class Solution:
    def countSubarrays(self, nums: List[int], k: int) -> int:
        n = len(nums)
        a = []
        mx =10**6
        for v in nums:
            if v < k:
                a.append(-1)
            elif v>k:
                a.append(1)
            else:
                a.append(mx)
        s = 0
        d = Counter()
        d[0] = 1
        ans = 0
        for i,v in enumerate(a):            
            s += v
            ans += d[s-mx]+d[s-mx-1]
            d[s] += 1            
        
        return ans

左右前缀和

class Solution:
    def countSubarrays(self, nums: List[int], k: int) -> int:
        n = len(nums)
        d = {(0,0,0):1}
        p = nums.index(k)
        ans = 1
        
        l,r = Counter(),Counter()
        s = 0
        for j in range(p+1,n):
            s += 1 if nums[j]>k else -1
            r[s] += 1
        ans += r[0]+r[1]
        s = 0
        for j in range(p-1,-1,-1):
            s += 1 if nums[j]>k else -1
            l[s] += 1
        ans += l[0]+l[1]
        
        ans += l[0]*r[0]
        for i in range(1,n):
            ans += l[i]*r[-i]+l[i]*r[-i+1]+r[i]*l[-i]+r[i]*l[-i+1]
        return ans

六、参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值