Day04
16. 最接近的三数之和 (Medium)
16. 最接近的三数之和 (Medium)
思路:此题思路与第十五题差不多,排序+双指针。
- 先对数组进行排序;
- 设置最大默认值res,目的是趋于最近的target并一直更新;
- 固定i,设立双指针left,right分别指向i+1和len(nums) - 1;
- 判断abs(sum - target) < abs(res - target),说明sum接近target,并更新res;
- 接下来对sum和target进行比较,因为数组是排序后的:若sum<target则左指针left+1向右移动;若sum>target,则右指针right-1向左移动,若sum=target则直接返回target.
"""
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
提示:
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^
"""
from typing import List
class Solution(object):
# 排序+双指针,类似第十五题
# Time complexity: O(N^2)
# Space complexity: O(1)
def threeSumClosest(self, nums: List[int], target: int) -> int:
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums = sorted(nums)
# 设置最大默认值,趋于最近的和并一直更新
res = float('inf')
for i in range(len(nums)):
# 固定i,并判断是否重复
if i > 0 and nums[i] == nums[i - 1]:
continue
# 设置左右双指针
left, right = i + 1, len(nums) - 1
while left < right:
sum = nums[i] + nums[left] + nums[right]
# 判断abs(sum - target) < abs(res - target),说明sum接近target,并更新res
if abs(sum - target) < abs(res - target):
res = sum
if sum < target:
left += 1
elif sum > target:
right -= 1
else:
return target
return target
20. 有效的括号 (Easy)
20. 有效的括号 (Easy)
思路:利用栈的特点(先进后出),见图stack.
- 首先,遍历字符串把所有左括号({[都放进栈里面;
- 然后若不是左括号的时候,此时从栈里剔除第一个括号,这里的第一个括号是最近进入的括号,并不是第一个进入栈的括号,即图stack的8;
- 此时需要检查栈里长度是否为0,若为0则说明只有右括号,因为栈里没有左括号与之匹配;
- 若栈里长度不为0,依次判断是否互相匹配,即()、[]、{};
- 当遍历完以后,仍然没有产生结果,则检查栈里长度是否为0,若为0则说明已经全部完成匹配,否则说明还有左括号,返回False。
"""
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
"""
class Solution_stack(object):
# 思路:栈方法,特点先进后出
# Time complexity: O(N)
# Space complexity: O(N)
def isValid(self, s: str) -> bool:
"""
:type s: str
:rtype: bool
"""
if len(s) == 0:
return True
# 建立栈
stack = []
for i in s:
# 遍历s,如果所有括号以左边为括号都全部加入到栈里面去
if i == '(' or i == '{' or i == '[':
stack.append(i)
else:
# 否则的话,先判断此时栈长度是否为0,如果栈为0,那说明此时i为单独的右括号)}],即不会产生配对,不满足有效字符串,返回False
if len(stack) == 0:
return False
else:
# 若此时栈长度不为0,则先把栈元素提出来temp,栈的特点先进后出.此时依次判断i与temp是否配对即可
temp = stack.pop()
if i == ')':
if temp != '(':
return False
elif i == '}':
if temp != '{':
return False
elif i == ']':
if temp != '[':
return False
# 若此时遍历完以后,都没有产生结果,则去判断栈里是否有字符串,有则说明还有左括号({[没有配对返回False,没有则说明全部配对完成返回True
return True if len(stack) == 0 else False
if __name__ == '__main__':
s1 = Solution_stack()
s = "()[]{}"
print(s1.isValid(s))
21. 合并两个有序链表 (Easy)
21. 合并两个有序链表 (Easy)
思路:此题为链表LinkList的题
-
迭代法
- leetcode第二题一样,链表的题,定义cur为可移动的result;
- 若l1.val <= l2.val,此时cur.next指向l1.val,然后l1往后移l1 = l1.next;
- 反之cur.next指向l2.val,然后l2往后移l2 = l1.next;
- 当l1或者l2位None,以l1:[1,2,3]和l2:[1,4,5]为例,当while循环进行完毕以后,整个过程是cur = cur.next 1->1->2>->3.此时l1.next为None了,跳出循环,cur = cur.next下一个指向l2的->4->5.
-
递归法
- 设定递归的终止条件;
- 同样的以l1:[1,2,3]和l2:[1,4,5]为例,当l1.val <= l2.val的时候,进行递归;
- 此时l1.val <= l2.val,l1指向l1.next,即剩下l1:[2,3]和l2:[1,4,5]进行递归;
- 此时l1.val > l2.val,l2指向l2.next,即剩下l1:[2,3]和l2:[4,5]进行递归;
- 此时l1.val < l2.val,l1指向l1.next,即剩下l1:[3]和l2:[4,5]进行递归;
- 此时l1.val < l2.val,l1指向l1.next,l2:[4,5]进行递归,跳出递归返回l2;
"""
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
见图21_Merge_Two_Sorted_Lists.png
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:
输入:l1 = [], l2 = []
输出:[]
示例 3:
输入:l1 = [], l2 = [0]
输出:[0]
提示:
两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列
"""
# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution_iteration:
# 思路:迭代法
# Time complexity: O(N)
# Space complexity: O(N)
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
"""
:type l1: ListNode[1,2,3]
:type l2: ListNode[1,4,5]
:rtype: ListNode
"""
res = ListNode()
# 与leetcode第二题一样,链表的题,定义cur为可移动的result
cur = res
while l1 != None and l2 != None:
# 若l1.val <= l2.val,此时cur.next指向l1.val,然后l1往后移l1 = l1.next
if l1.val <= l2.val:
cur.next = l1
l1 = l1.next
else:
# 反之cur.next指向l2.val,然后l2往后移l2 = l1.next
cur.next = l2
l2 = l2.next
cur = cur.next
# 当l1或者l2位None,以l1:[1,2,3]和l2:[1,4,5]为例,当while循环进行完毕以后,整个过程是cur = 1->1->2>->3.
# 此时l1.next为None了,跳出循环,cur = cur.next下一个指向l2的->4->5.
cur.next = l1 or l2
return res.next
class Solution_recursion:
# 思路:递归法
# Time complexity: O(M+N)
# Space complexity: O(M+N)
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
"""
:type l1: ListNode[1,2,3]
:type l2: ListNode[1,4,5]
:rtype: ListNode
"""
# 设定递归的终止条件
if l1 == None or l2 == None:
return l1 or l2
# 同样的以l1:[1,2,3]和l2:[1,4,5]为例,当l1.val <= l2.val的时候,进行递归.
# 1.此时l1.val <= l2.val,l1指向l1.next,即剩下l1:[2,3]和l2:[1,4,5]进行递归;
# 2.此时l1.val > l2.val,l2指向l2.next,即剩下l1:[2,3]和l2:[4,5]进行递归;
# 3.此时l1.val < l2.val,l1指向l1.next,即剩下l1:[3]和l2:[4,5]进行递归;
# 4.此时l1.val < l2.val,l1指向l1.next,l2:[4,5]进行递归,跳出递归返回l2;
if l1.val <= l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
参考资料
BiliBili爱学习的饲养员