记录一些值得二刷,或者让人惊艳的想法。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)