leetcode刷题:第一周
leetcode刷题:第二周
leetcode刷题:二分查找
leetcode刷题:双指针
本次博客内容记录一些有关双指针的算法题。
给定一个已排序的链表的头 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
给你一个包含 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
给定 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)
给定两个由一些 闭区间 组成的列表,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
给定一个长度为 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
算法之路,然终而道远。