- 0016题目 LeetCode0016
思路:就是先排序,然后双指针遍历一下,先考虑枚举第一个元素 a,对于剩下的两个元素 b 和 c,我们希望它们的和最接近target−a,设数组的长度为 n,我们先枚举 a,它在数组中的位置为 i;为了防止重复,我们在位置 [i+1, n)的范围内枚举 b 和 c,b从i+i开始向后遍历,然后c从n向i+i反向遍历,直到相遇为止,如果 a+b+c≥target,那么就将c向左移动一个位置,反之b向右移动一个位置。
代码:
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
n = len(nums)
best = 10 ** 7
# 根据差值的绝对值来更新答案
def update(cur):
nonlocal best
if abs(cur - target) < abs(best - target):
best = cur
# 枚举 a
for i in range(n):
# 保证和上一次枚举的元素不相等
if i > 0 and nums[i] == nums[i - 1]:
continue
# 使用双指针枚举 b 和 c
j, k = i + 1, n - 1
while j < k:
s = nums[i] + nums[j] + nums[k]
# 如果和为 target 直接返回答案
if s == target:
return target
update(s)
if s > target:
# 如果和大于 target,移动 c 对应的指针
k0 = k - 1
# 移动到下一个不相等的元素
while j < k0 and nums[k0] == nums[k]:
k0 -= 1
k = k0
else:
# 如果和小于 target,移动 b 对应的指针
j0 = j + 1
# 移动到下一个不相等的元素
while j0 < k and nums[j0] == nums[j]:
j0 += 1
j = j0
return best
- 0020题目LeetCode0020
思路:巧用栈的思路,遇到左括号直接进栈,然后遇见右括号的话,就开始与其之前的另一个括号去匹配,匹配成功返回TRUE,失败直接返回FALSE。
代码:
class Solution:
def isValid(self, s: str) -> bool:
dic = {'{': '}', '[': ']', '(': ')', '?': '?'}
stack = ['?']
for c in s:
if c in dic: stack.append(c)
elif dic[stack.pop()] != c: return False
return len(stack) == 1
顺便再次强调一下pop()这个知识点,pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。默认删除最后一个,简直就是为这个题目量身定做的一个函数,哈哈,开玩笑啦,pop()的功能不至于此。。。
结果:
- 题目0021:LeetCode0021
思路:直接暴力解法即可,定义一个哑结点,然后用两个指针分别去遍历l1和l2两个链表,遍历的同时不忘了比较l1和l2的值,然后将哑结点的下一个节点指向l1和l2中比较小的那个结点即可,然后分别l1和l2依次向下顺延,直至结束,别忘了考虑两种特殊情况,链表为或者是两个链表之中有一个已经结束的情况。这里考虑过递归,但是递归的空间复杂度比较大,所以没有采用递归求解。
代码:
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
prehead = ListNode(-1)
prev = prehead
while l1 and l2:
if l1.val <= l2.val:
prev.next = l1
l1 = l1.next
else:
prev.next = l2
l2 = l2.next
prev = prev.next
prev.next = l1 if l1 is not None else l2
return prehead.next