1.数组中的第k个最大元素https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
看到这题只想到排序之后取第k个元素,那就是一个最基本的排序问题了
看了解答之后理解了“快速选择”思想,即在快排的过程中只递归目标方向。
1 import random 2 class Solution: 3 def quickSelect(self, a, l, r, index): 4 q = self.randomPartition(a, l, r) 5 if q == index: 6 return a[q] 7 else: 8 return self.quickSelect(a, q+1, r, index) if q < index else self.quickSelect(a, l, q-1, index) 9 def randomPartition(self, a, l, r): 10 i = random.randint(l, r) 11 a[i], a[r] = a[r], a[i] 12 return self.partition(a, l, r) 13 def partition(self, a, l, r): 14 x = a[r] 15 i = l - 1 16 for j in range(l, r): 17 if a[j] < x: 18 i += 1 19 a[i], a[j] = a[j], a[i] 20 i += 1 21 a[i], a[r] = a[r], a[i] 22 return i 23 24 def findKthLargest(self, nums, k): 25 return self.quickSelect(nums, 0, len(nums)-1, len(nums)-k)
官方解答提出了第二种思想:堆排序+删除,这个在当时数据结构里有记过,现在都忘了。在这里重新结合代码进行理解记忆感觉很有帮助。不过此方法比第一种快速选择方法时间复杂度要高一些。
1 class Solution: 2 def findKthLargest(self, nums: List[int], k: int) -> int: 3 4 def adju_max_heap(nums_list, in_node): # 从当前内部节点处修正大根堆 5 """"in_node是内部节点的索引""" 6 l, r, large_idx= 2*in_node+1, 2*in_node+2, in_node # 最大值的索引默认为该内部节点 7 8 if l < len(nums_list) and nums_list[large_idx] < nums[l]: 9 # 如果左孩子值大于该内部节点的值,则最大值索引指向左孩子 10 large_idx = l 11 if r < len(nums_list) and nums_list[large_idx] < nums[r]: 12 # 如果执行了上一个if语句,此时最大值索引指向左孩子,否则还是指向该内部节点 13 # 然后最大值索引指向的值和右孩子的值比较 14 large_idx = r 15 16 # 上述两个if就是得到(内部节点,左孩子,右孩子)中最大值的索引 17 if large_idx != in_node: # 如果最大值在左孩子和右孩子中,则和内部节点交换 18 nums_list[large_idx], nums_list[in_node] = nums_list[in_node], nums_list[large_idx] 19 # 如何内部节点是和左孩子交换,那就递归修正它的左子树,否则递归修正它的右子树 20 adju_max_heap(nums_list, large_idx) 21 22 def build_max_heap(nums_list): # 由列表建立大根堆 23 """"从后往前遍历所有内部节点,其中最后一个内部节点的公式为len(nums_list)//2 - 1""" 24 for in_node in range(len(nums_list)//2 - 1, -1, -1): 25 adju_max_heap(nums_list, in_node) 26 27 def find_kth_max(nums_list, k): # 从列表中找到第k个最大的 28 build_max_heap(nums_list) # 先建立大根堆 29 for _ in range(k-1): 30 nums_list[0], nums_list[-1] = nums_list[-1], nums_list[0] # 堆头和堆尾交换 31 nums_list.pop() # 删除堆尾 32 adju_max_heap(nums_list, 0) # 从堆头处开始修正大根堆 33 return nums_list[0] 34 return find_kth_max(nums, k)
2.存在重复元素https://leetcode-cn.com/problems/contains-duplicate/
简单题,学到了python的set()方法
1 class Solution: 2 def containsDuplicate(self, nums: List[int]) -> bool: 3 return len(nums) != len(set(nums))
3.二叉搜索树中第k小的元素https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst/