LeetCode复习总结(摩尔投票,多路归并,蓄水池抽样等)

记录一些值得二刷,或者让人惊艳的想法。DP,BFS等更经典,但次数较多,用着用着就会了,这些比较少见,可以重复学学看看

排序算法还是值得一看,面试被问,都有点无法回答,sort()用多了后遗症(是真好用啊),快速排序,桶排序,堆排序等

'''
摩尔投票法值得学习下
leetcode229题求众数:给定一个大小为 n 的数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
输入: [3,2,3]
输出: [3]
'''
#第一次解法:
def majorityElement(self, nums: List[int]) -> List[int]:
        from collections import defaultdict
        dic = defaultdict(int)
        for i in nums:
            dic[i]+=1
        num = len(nums)/3
        reList = []
        for key in dic:
            if dic[key]> num:
                reList.append(key)
        return reList
#参考摩尔投票法,“在任何数组中,出现次数大于该数组长度一半的值只能有一个。”,推广到1/3,“在任何数组中,出现次数大于该数组长度1/3的值最多只有两个。”所以不需要set来进行记录
def majorityElement(self, nums: List[int]) -> List[int]:
        count1, count2 = 0, 0
        res1, res2 = None, None
        res = []
        for num in nums:
            if count1 == 0 and num != res2:
                count1 = 1
                res1 = num
                continue
            elif count2 == 0 and num != res1:
                count2 = 1
                res2 = num
                continue
            if num == res1:
                count1 += 1
            elif num == res2:
                count2 += 1
            else:
                count1 -= 1
                count2 -= 1
        count1, count2 = 0, 0
        for num in nums:
            if num == res1:
                count1 += 1
            elif num == res2:
                count2 += 1
        if count1 > len(nums)/3:
            res.append(res1)
        if count2 > len(nums)/3:
            res.append(res2)
        return res

'''
leetcode238题,给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。请不要使用除法,且在 O(n) 时间复杂度内完成此题。
输入: [1,2,3,4]
输出: [24,12,8,6]
'''
#一脸懵逼,看了评论才知道,用正向反向各乘一次即可
def productExceptSelf(self, nums: List[int]) -> List[int]:
    res, l, r = [1] * len(nums), 1, 1
    for i, j in zip(range(len(nums)), reversed(range(len(nums)))):
		
	res[i], l = res[i] * l, l * nums[i]
	res[j], r = res[j] * r, r * nums[j]
    return res

'''
多路归并
leetcode378题:
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。
matrix = [
   [ 1,  5,  9],
   [10, 11, 13],
   [12, 13, 15]
],k = 8
返回 13。
'''
def kSmallestPairs(self, matrix,k):
	n = len(matrix)
	# 归并 n路归并,矩阵每一行作为一路 O(nk)
	index = [0] * n
	result = []
	while len(result) <= k:
		minone = 0, float('inf')
		for i in range(n):
			if index[i] == -1:
				continue
			if matrix[i][index[i]] < minone[1]:
				minone = i, matrix[i][index[i]]
		result.append(minone[1])
		index[minone[0]] += 1
		if index[minone[0]] >= n:
			index[minone[0]] = -1
	return result[k - 1]

'''
蓄水池抽样算法(可通过概率得证,1/n取样概率同样大)
leetcode382题:
给定一个单链表,随机选择链表的一个节点,并返回相应的节点值。保证每个节点被选的概率一样。链表十分大且长度未知,常数级空间复杂度实现
'''
class Solution:
    def __init__(self, head: ListNode):
        self.head = head

    def getRandom(self) -> int:
        count, res = 1, -1
        cur = self.head
        while cur:
            if int(random.random()*count) == 0:
                res = cur.val
            count, cur = count + 1, cur.next
        return res

'''
最长子串问题,分治迭代
leetcode395题:
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
输入:
s = "aaabb", k = 3
输出:
3
最长子串为 "aaa" ,其中 'a' 重复了 3 次。
'''
# 分治迭代,最大的亮点在于如果每个字符都大于k则一定输出了全部,所以只需要找不大于k的字符然后从字符处切割,且在迭代时必定时包含关系,return max剪枝了。
# 还有一个小亮点在于求一个list或者str里的字符个数,可以set(s),遍历count.这是一个小技巧
def longestSubstring(self, s: str, k: int) -> int:
	if not s:
		return 0
	for c in set(s):
		if s.count(c) < k:
			return max(self.longestSubstring(t, k) for t in s.split(c))
	return len(s)

 

你可能感兴趣的:(#,leetcode)