16、最接近的三数之和
把三数和转化为两数和:固定住一个数,求出sum=target-这个数,在剩下的数中用双指针找到和sum最接近的值。
时O(nlogn+n^2)=O(n^2) 额外空O(1) 排序O(logn)
优化思路:
(1)三数和=target时直接return target
(2)加一个判重操作,如果left+=1或者right-=1之后的数和left/right之前的值一样直接往下移。
(3)mark的初值不用再循环中每次判断,直接在循环之外用随便三个nums[i]的值初始化即可,但是绝对不能自己设定初始化的值。
class Solution(object):
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums.sort()
l = len(nums)
mark = 0
for i in range(l):
sum = target - nums[i]
left = i+1
right = l-1
while left < right:
tmp = sum - (nums[left] + nums[right])
if i == 0 and left == 1 and right == l-1: #用第一个值初始化mark
mark = tmp
else:
if abs(tmp) < abs(mark):
mark = tmp
if tmp == 0:
return target
elif tmp > 0:
left +=1
else:
right -=1
return target - mark
17、电话号码的字母组合
1、回溯法,用递归模板
2、递归是DFS,改为BFS,用队列做,三重循环,第一层遍历数字,第二层循环把当前队列里的字符串出队,第三层循环把下一个数字对应的字符与出队的字符串相连接入队。
class Solution(object):
def letterCombinations(self, digits):
"""
:type digits: str
:rtype: List[str]
"""
if digits == '':
return []
phone = ['abc','def','ghi','jkl','mno','pqrs','tuv','wxyz']
ans = []
patch = []
l = len(digits)
def backtracking(digits,index): #参数 index对应:控制了迭代循环最外层的次数 即数字个数
if index == l: #终止条件
ans.append(''.join(patch)) #收集结果
return #return
for i in phone[ord(digits[index]) - 50]: #第二层循环 处理集合元素
patch.append(i) #处理节点
backtracking(digits,index+1) #递归 第三层循环
patch.pop() #回溯
backtracking(digits,0)
return ans
问题:这里patch定义为全局变量 ,但是在终止条件那里如果写ans.append(patch),会报错说局部变量patch未指定,这是为什么,改为ans.apppend('',join(patch))就不会报错了。
class Solution(object):
def letterCombinations(self, digits):
"""
:type digits: str
:rtype: List[str]
"""
if digits == '':
return []
phone = ['abc','def','ghi','jkl','mno','pqrs','tuv','wxyz']
ans = ['']
for i in digits:
l = len(ans)
for _ in range(l):
tmp = ans.pop(0)
for j in phone[ord(i) - 50]: #ord[i]-48的结果是2对应2,0对应0
#但是这里phone的第0个元素对应2,所以-48变成了-50
ans.append(tmp + j)
return ans
19、删除链表的倒数第N个结点
1、先遍历链表看一共有几个结点,再减去倒数就得到正数第几个结点。
对于特殊情况(仅有一个结点,去除头节点)特殊处理。
2、先后指针,快指针先走n步,随后再快慢指针一起走,当快指针到末尾时,慢指针就到了倒数第n个结点的前一个结点。注意要特殊处理删除头节点,即倒数第n个为头节点的情况。
如果不特殊处理头节点,就要新建一个结点dummy.next指向头节点,让慢指针也等于这个结点dummy,最后return dummy.next
3、也可以用栈实现,先入栈,再出栈,第n个出来的即为倒数第n个,栈顶元素即为倒数n-1个。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
index = head
if head.next == None: #如果只有一个结点 那肯定返回None
return None
l = 0
while head: #计数一共有多少个结点
head = head.next
l+=1
t = l - n #记录是正数第几个节点
if t == 0: #如果要去除的是正数第1个节点 直接return index.next
return index.next
head = index #否则要一直遍历到第t个结点
while t > 0:
t-=1
tmp = head
head = head.next
tmp.next = head.next
return index
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
fast = slow = head
while n>0: #让快指针先走n步
fast = fast.next
n-=1
if fast == None: #如果此时快指针为空,即要删的是头节点直接return head.next
return head.next
while fast and fast.next: #否则快指针走到链表结尾时,慢指针正好走到了倒数第n个结点的前一个
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return head