目录
一、链表
二、二叉树
三、前缀和
四、动态规划
五、堆排序
本文会列举几道比较常见的题目中带有 “K” 的问题,有的问题在我的另一篇博客里做了详细的解释,所以这篇文章里我就不做太多解释
1、返回倒数第 k 个节点
输入: 1->2->3->4->5 和 k = 2 输出: 4
class Solution:
def kthToLast(self, head: ListNode, k: int) -> int:
fast = head
slow = head
while k!=0:
fast = fast.next
k-=1
while fast:
fast = fast.next
slow = slow.next
return slow.val
先让快指针走k步,然后再同时走,快指针走到结尾时慢指针就走到第k个节点了
2、合并 K 个排序链表
输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
if not lists:return None
return self.helper(lists,0,len(lists)-1)
def helper(self,lists,l,r):
if l==r:
return lists[l]
# if l>r:
# return None
mid = l + (r - l) // 2
l1 = self.helper(lists,l,mid)
l2 = self.helper(lists,mid+1,r)
return self.mergeTwoList(l1, l2)
def mergeTwoList(self,A,B):
if not A or not B:
return B if not A else A
cur = ListNode(-1)
tmp = cur
while A and B:
if A.val<=B.val:
tmp.next = A
A = A.next
else:
tmp.next = B
B = B.next
tmp = tmp.next
tmp.next = A if A else B
return cur.next
使用二分法来两两合并链表
二叉搜索树的第 k 大节点
输入: root = [3,1,4,null,2], k = 1 3 / \ 1 4 \ 2 输出: 4
递归版写法:
class Solution:
count = 0
res = 0
def kthLargest(self, root: TreeNode, k: int) -> int:
return self.helper(root,k)
def helper(self,root,k):
if not root:
return
self.helper(root.right,k)
self.count +=1
if k==self.count:
self.res = root.val
self.helper(root.left,k)
return self.res
迭代版写法:
class Solution:
def kthLargest(self, root: TreeNode, k: int) -> int:
if not root:
return None
stack = []
node = root
while node or len(stack)>0:
while node:
stack.append(node)
node = node.right
node = stack.pop()
if k==1:
self.res = node.val
k-=1
node = node.left
return self.res
和为 K 的子数组
输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
第一眼看到题,我还以为是和 组合总和 这道题一样
输入: candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]
于是上来就套用回溯模板,当然最后答案是错的,看了解析发现是用前缀和。
什么是前缀和呢?其实就是数组当前项的总和
字典的键为前缀和,即从第 0 项到当前项的总和,值为这个 前缀和 值出现了几次
遍历 nums 之前,我们预置边界情况 (即之前提到的 prefixSum [-1] = 0):map 初始放入 0:1 键值对,即预设已经出现 1 次为 0 的前缀和
遍历 nums 的每一项,求当前项的前缀和,存入 map 中
之前没有存过,则存入,初始值为 1
之前存过,则对应值 +1,即出现次数 +1
边存边查看 map ,如果 map 中已存在 key 为 当前前缀和 - k
说明存在 【之前求出的前缀和】,它的值满足 【当前前缀和】-【之前求出的前缀和】 == k
把 【之前求出的前缀和】 出现的次数,累加给 count 计数器
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
if not nums:
return 0
dic = dict()
dic[0] = 1
acc = 0
count = 0
for num in nums:
acc += num
if (acc-k) in dic:
count+=dic[acc-k]
if acc not in dic:
dic[acc] = 1
else:
dic[acc] += 1
return count
第 k 个数
这道题实际上是和 丑数 这道题类似的,这里使用的是动态规划的做法,当然也可以用堆的做法,这里就不介绍堆的用法
这是使用三指针的dp做法
class Solution:
def getKthMagicNumber(self, k: int) -> int:
a,b,c = 0,0,0
dp = [1]*k
for i in range(1,k):
n1,n2,n3 = dp[a]*3,dp[b]*5,dp[c]*7
dp[i] = min(n1,n2,n3)
if dp[i]==n1:
a+=1
if dp[i]==n2:
b+=1
if dp[i]==n3:
c+=1
return dp[-1]
堆排序这章的内容在我的博客 https://blog.csdn.net/Matrix_cc/article/details/106606612 里已有介绍,这里就不介绍了
参考:
leetcode题解中的一些解释