Leetcode Day13 双指针

392 判断一个str是不是另一个str的子序列(不用连续)

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        if len(t) < len(s):
            return False
        l = 0
        r = 0
        while l < len(s):
            if s[l] == t[r]:
                l += 1
                r += 1
            else:
                r += 1
            if r >= len(t):
                return l == len(s)
        return True

自己写的双指针, 有点丑陋

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        i, j = 0, 0
        while i < len(s) and j < len(t):
            if s[i] == t[j]:
                i += 1
            j += 1
        return i == len(s)

学习一下标答

15 三数之和(经经典典)

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        ans = []
        n = len(nums)
        for i in range(n):
            l = i + 1
            r = n - 1
            if i > 0 and nums[i] == nums[i-1]: # 对i去重
                continue
            while l < r:
                target = 0
                x = nums[i]
                L = nums[l]
                R = nums[r]
                if x + L + R > target:
                    r -= 1
                elif x + L + R < target:
                    l += 1
                else:
                    ans.append([x, L, R])
                    l += 1
                    r -= 1
                    while l < r and  nums[l] == nums[l-1]: # 对l去重, 注意这个部分应该在target == 0的时候才去重
                        l += 1
                    while l < r and  nums[r] == nums[r+1]: # 对r去重, 注意这个部分应该在target == 0的时候才去重
                        r -= 1
        return ans

复杂度分析: O ( n 2 ) O(n^2) O(n2)

206 翻转列表

class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        dummy = None
        prev = dummy
        cur = head
        while cur:
            nxt = cur.next
            cur.next = prev
            prev = cur
            cur = nxt
        return prev

特别注意这个情况是不能使用dummy head的,
1.是因为翻转过后第一个元素应该是None
2.否则会发生环的情况, 我来具体解释一下:
dummy -> 1 -> 2
dummy <----> 1 -> (经过cur.next = prev)

19 删除列表的倒数第N个节点

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        # 创建一个虚拟节点,并将其下一个指针设置为链表的头部
        dummy_head = ListNode(0, head)
        
        # 创建两个指针,慢指针和快指针,并将它们初始化为虚拟节点
        slow = fast = dummy_head
        
        # 快指针比慢指针快 n+1 步
        for i in range(n+1):
            fast = fast.next
        
        # 移动两个指针,直到快速指针到达链表的末尾
        while fast:
            slow = slow.next
            fast = fast.next
        
        # 通过更新第 (n-1) 个节点的 next 指针删除第 n 个节点
        slow.next = slow.next.next
        
        return dummy_head.next

几个问题

  • fast和slow都从哪里开始
  • 为什么需要dummy
  • 最后为什么返回dummy.next而不是一开始head的copy
    一个思想解决: 当r到达none是, l应该是倒数第n个, 此时l, r的index分别是len - n, len. 从这个状态一直往回推, 我们可以得到0, n

160 相交链表

在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
        if headA == None or headB == None:
            return None
        l = headA
        r = headB
        while l != r:
            if l == None:
                l = headB
            else:
                l = l.next
            if r == None:
                r = headA
            else:
                r = r.next
        return l

情况1: 有环, 则在相交点遇上对方
情况2: 无环, 则在最小公倍数次数之后在None遇见

18 四数之和

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        n = len(nums)
        ans = []

        for i in range(n): 
            for j in range(n - 1, i, -1):
                if i > 0 and nums[i] == nums[i - 1]:
                    continue
                if j < len(nums) - 1 and nums[j] == nums[j + 1]:
                    continue
                l = i + 1
                r = j - 1
                while l < r:
                    cur_sum = nums[i] + nums[j] + nums[l] + nums[r]
                    if cur_sum < target:
                        l += 1
                    elif cur_sum > target:
                        r -= 1
                    else:
                        ans.append([nums[i], nums[j], nums[l], nums[r]])
                        l += 1
                        r -= 1
                        while l < r and nums[l] == nums[l-1]:
                            l += 1
                        while l < r and nums[r] == nums[r + 1]:
                            r -= 1
        return ans  

情况只能说是一模一样, 只需要在三数之和的基础上再套一层for循环即可

复杂度分析: O ( n 3 ) O(n^3) O(n3)

42 接雨水

一个自然的想法是对于一个木桶, 看左边最高和右边最高就可以了, 但这个情况就需要我们用两个数组来储存, 用双指针的方法可以把空间复杂度降下来.

对于一个桶, 如果前缀最大小, 那么这个桶的容量已经可以计算了

class Solution:
    def trap(self, height: List[int]) -> int:
        ans = left = pre_max = suf_max = 0
        right = len(height) - 1
        while left < right:
            pre_max = max(pre_max, height[left])
            suf_max = max(suf_max, height[right])
            if pre_max < suf_max:
                ans += pre_max - height[left]
                left += 1
            else:
                ans += suf_max - height[right]
                right -= 1
        return ans
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值