LeetCode Q16-Q20
Q16 最接近的三数之和 3Sum Closest
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
这道题和3Sum没什么太大的区别,把目标值0换成了target,最后也是用双指针然后解决的这道题
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
minDif=2**31-1
for i in range(len(nums)):
left=i+1
right=len(nums)-1
while left<right:
if abs((nums[i]+nums[left]+nums[right])-target)<minDif:
sol=nums[i]+nums[left]+nums[right]
minDif=abs((nums[i]+nums[left]+nums[right])-target)
if nums[i]+nums[left]+nums[right]<target:
left+=1
elif nums[i]+nums[left]+nums[right]>target:
right-=1
else:
return target
return sol
Q17 电话号码的字母组合 Letter Combination of a Phone Number
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
这道题我用的是递归的方法,由于很久没有使用递归,我在这上面花了一些时间
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
if digits=="":
return []
lst_letter={"2":"abc","3":"def","4":"ghi","5":"jkl","6":"mno","7":"pqrs","8":"tuv","9":"wxyz"}
lst_sol=[""]
def returnLetter(digits,lst_sol):
if not digits: #终止递归
return lst_sol
lst=[]
for i in range(len(lst_sol)):
for j in range(len(lst_letter[digits[0]])):
lst.append(lst_sol[i]+lst_letter[digits[0]][j])
lst_sol=lst
return returnLetter(digits[1:],lst_sol)
return returnLetter(digits,lst_sol)
需要注意的是递归一定要有个跳出的判断,不然会陷入死循环,这个方法很明显并不高效,但是这是我对这种题目的一个下意识的思路,高效的解法是摘自一个大神的:
class Solution:
def letterCombinations(self, digits: str) -> list:
KEY = {'2': ['a', 'b', 'c'],
'3': ['d', 'e', 'f'],
'4': ['g', 'h', 'i'],
'5': ['j', 'k', 'l'],
'6': ['m', 'n', 'o'],
'7': ['p', 'q', 'r', 's'],
'8': ['t', 'u', 'v'],
'9': ['w', 'x', 'y', 'z']}
if digits == '':
return []
ans = ['']
for num in digits:
ans = [pre+suf for pre in ans for suf in KEY[num]]
return ans
他厉害的地方在于用了python中for循环在字符串和列表的应用,直接遍历了每一个字符串再让它们相加,可以学一下,因为之前在其他语言中并不会想到
Q18 四数之和 4Sum
不写了,太恶心了,来个NSum得了
Q19 删除链表的倒数第 N 个结点 Remove Nth Node from End of List
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
链表的使用确实还不太熟悉,这道题废了半天的劲也是写出来了,只是我用的方法是遍历两次,先得出链表的长度,再根据长度减去n获得正序的索引位置进而删除,太麻烦了。
下面这个是看的别人写的,它先用了一个链表a遍历到第n个节点,然后再与b同时遍历直到a遍历完成,这时候b的下一个节点便是倒数第n个节点,🐂🍺
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
a = head
b = head
for i in range(n):
if a.next:
a = a.next
else:
return head.next
while a.next:
a = a.next
b = b.next
b.next = b.next.next
return head
链表中需要着重注意的是要知道遍历的条件(通常为b.next
不为空时),除此之外也需要注意若是要改变节点的链接,需要让b.next受到改变,如b.next = b.next.next
,而不是让当前节点b=b.next.next
,这只会发生指针跳转而不会改变节点。
Q20 有效的括号 Valid Parentheses
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
怎么说呢,用了正则表达式写了半天(虽然这个想法从一开始就不太好用),不如别人的灵机一动,这种种类不多的固定字符串形式感觉都可以用这种方法来写。
class Solution:
def isValid(self, s: str) -> bool:
while '{}' in s or '()' in s or '[]' in s:
s = s.replace('{}', '')
s = s.replace('[]', '')
s = s.replace('()', '')
return s == ''
它无数次遍历找寻三种括号的集合直到找不到为止,每找到一次就替换为空格,最后符合标准的字符串将全部转为空格,直接返回判断值就行。我能说啥呢,🐂🍺
Q16-Q20 一些笔记
-
递归的时候不要忘记跳出的语句
-
类下的方法中的方法可以不用在参数中加
self
-
for循环可以用于字符串与列表,如Q17:
ans = [''] for num in digits: #for在字符串中遍历 ans = [pre+suf for pre in ans for suf in KEY[num]] #for在字符串与列表中遍历
-
若要改变链表的节点连接,需要让
b.next
受到改变,如b.next = b.next.next
,而不是让当前节点b=b.next.next
,这只会让指针跳到下下个节点而不会改变节点的链接。 -
若
head
是链表的第一个元素,使b=head
,遍历b
时不会让head
发生改变。若想改变head,参照第四条笔记,让b.next发生改变,使得链表节点链接改变 -
Q20这种替换字符串的方法适用于一些找特定字符串组合的题目,多留意一下这种方法吧
再多写一些链表题目吧,把速度加快一些,有时候刷题会让自己越来越灰心,觉得自己总是想不到最好的解决方法,但是没办法,加油干吧。