leetcode刷题:双指针

系列文章目录

leetcode刷题:第一周
leetcode刷题:第二周
leetcode刷题:二分查找
leetcode刷题:双指针


文章目录

  • 系列文章目录
  • 前言
  • 双指针
    • 1.删除排序链表中的重复元素 II
    • 2.三数之和
    • 3.比较含退格的字符串
    • 4.区间列表的交集
    • 5.盛最多水的容器
  • 总结


前言

本次博客内容记录一些有关双指针的算法题。


双指针

1.删除排序链表中的重复元素 II

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表。

示例 1:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]

示例 2:
输入:head = [1,1,1,2,3]
输出:[2,3]

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


class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        # 链表只记录算法
        if not head:
            return head
        #建立一个哑节点,用来指向头节点
        dummy = ListNode(0, head)

        cur = dummy
        while cur.next and cur.next.next:
        	#当练习两个节点相同时,记录节点值
            if cur.next.val == cur.next.next.val:
                x = cur.next.val
                #删除重复节点
                while cur.next and cur.next.val == x:
                    cur.next = cur.next.next
            else:
                cur = cur.next
        #返回哑节点的下一个节点,即头节点
        return dummy.next

2.三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例 2:
输入:nums = []
输出:[]

示例 3:
输入:nums = [0]
输出:[]

#将三数之和转变成二数之和
class Solution:
    def __init__(self):
        self.nums = [-1, 0, 1, 2, -1, -4]

    def threeSum(self):
        nums = self.nums
        # 算法部分
        nums.sort()
        n = len(nums)
        ans = []
        for first in range(n):
        	#去除相同的数
            if first > 0 and nums[first] == nums[first - 1]:
                continue
            third = n - 1
            #目标数为第一个数的相反数
            target = -nums[first]
            #两数之和
            for second in range(first + 1, n):
            	#保证遍历没有遗漏
                if second > first + 1 and nums[second] == nums[second - 1]:
                    continue
                while second < third and nums[second] + nums[third] > target:
                    third -= 1
                if second == third:
                    break
                if nums[second] + nums[third] == target:
                    ans.append([nums[first], nums[second], nums[third]])
        return ans

3.比较含退格的字符串

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。

注意:如果对空文本输入退格字符,文本继续为空。

示例 1:
输入:s = “ab#c”, t = “ad#c”
输出:true
解释:s 和 t 都会变成 “ac”。

示例 2:
输入:s = “ab##”, t = “c#d#”
输出:true
解释:s 和 t 都会变成 “”。

示例 3:
输入:s = “a#c”, t = “b”
输出:false
解释:s 会变成 “c”,但 t 仍然是 “b”。

#利用了栈的性质
class Solution:
    def __init__(self):
        self.s = "ab#c"
        self.t = "ad#c"

    def backspaceCompare(self):
        s = self.s
        t = self.t

        # 算法部分
        def build(s):
            ret = []
            #当字符是#,弹出字符,否则压入字符
            for ch in s:
                if ch != '#':
                    ret.append(ch)
                elif ret:
                    ret.pop()
            return "".join(ret)

        return build(s) == build(t)

4.区间列表的交集

给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] = [starti, endi] 而 secondList[j] = [startj, endj] 。每个区间列表都是成对 不相交 的,并且 已经排序 。

返回这 两个区间列表的交集 。

形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b 。

两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3] 。

示例 1:
输入:firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]

示例 2:
输入:firstList = [[1,3],[5,9]], secondList = []
输出:[]

示例 3:
输入:firstList = [], secondList = [[4,8],[10,12]]
输出:[]

示例 4:
输入:firstList = [[1,7]], secondList = [[3,10]]
输出:[[3,7]]

class Solution:
    def __init__(self):
        self.firstList = [[0, 2], [5, 10], [13, 23], [24, 25]]
        self.secondList = [[1, 5], [8, 12], [15, 24], [25, 26]]

    def intervalIntersection(self):
        firstList = self.firstList
        secondList = self.secondList
        # 算法逻辑(没看懂)
        ans = []
        i = j = 0

        while i < len(firstList) and j < len(secondList):
            lo = max(firstList[i][0], secondList[j][0])
            hi = min(firstList[i][1], secondList[j][1])
            if lo <= hi:
                ans.append([lo, hi])
            if firstList[i][1] < secondList[j][1]:
                i += 1
            else:
                j += 1
        return ans

5.盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:
输入:height = [1,1]
输出:1

class Solution:
    def __init__(self):
        self.height = [1, 8, 6, 2, 5, 4, 8, 3, 7]

    def maxArea(self):
        height = self.height
        # 算法部分
        #创建双指针,逐渐向中间靠近,寻求最大值
        l, r = 0, len(height) - 1
        ans = 0
        while l < r:
            area = min(height[l], height[r]) * (r - l)
            ans = max(ans, area)
            #那边小,移动那边的指针
            if height[l] <= height[r]:
                l += 1
            else:
                r -= 1
        return ans

总结

算法之路,然终而道远。

你可能感兴趣的:(leetcode,leetcode,链表,算法)