# 261
class UnionFind:
def __init__(self, n):
self.n = n
self.part = n
self.parent = [x for x in range(n)]
self.size = [1 for _ in range(n)]
def Find(self, x: int) -> int:
if self.parent[x] == x:
return x
return self.Find(self.parent[x])
def Union(self, x: int, y: int) -> bool:
root_x = self.Find(x)
root_y = self.Find(y)
if root_x == root_y:
return False
if self.size[root_x] > self.size[root_y]:
root_x, root_y = root_y, root_x
self.parent[root_x] = root_y
self.size[root_y] += self.size[root_x]
self.part -= 1
def connected(self, x: int, y: int) -> bool:
return self.Find(x) == self.Find(y)
def get_part_size(self, x: int) -> int:
root_x = self.Find(x)
return self.size[root_x]
class Solution:
def validTree(self, n: int, edges: List[List[int]]) -> bool:
UF = UnionFind(n)
for x, y in edges:
if UF.Union(x, y) == False: #失败了,说明已经在一个连通域中了。再连接就是环了
return False
return UF.part == 1
# 263
class Solution:
def isUgly(self, num):
for i in [2,3,5]:
while num % i == 0 and num > 0:
num = num/i
return num == 1
# 264
class Solution:
def nthUglyNumber(self, n: int) -> int:
dp = [0] * n
dp[0] = 1
l2 = 0
l3 = 0
l5 = 0
for i in range(1 , n):
dp[i] = min(2 * dp[l2] , 3 * dp[l3] , 5 * dp[l5])
if dp[i] == 2 * dp[l2]:
l2 += 1
if dp[i] == 3 * dp[l3]:
l3 += 1
if dp[i] == 5 * dp[l5]:
l5 += 1
return dp[-1]
# 265
class Solution:
def minCostII(self, costs: List[List[int]]) -> int:
n = len(costs)
if not n:
return 0
k = len(costs[0])
# 初始化,minn为最小花费,min_color为它对应的颜色,minsec为第二小花费
minn = float('inf')
min_color = -1;
minsec = float('inf')
# 开始遍历
for i in range(n):
# temp前缀的为0-i房子的最小花费,颜色,第二小花费,
# i房子遍历结束,更新上面的minn,min_color,minsec,用于i+1的计算
tempmin = float('inf')
tempcolor = -1
tempminsec = float('inf')
# tempcost计算之前的dp[i][j]
tempcost = 0
# 遍历j,计算原来的dp[i][j]
for j in range(k):
tempcost = costs[i][j]
# 如果此时为房子0,不需要加后面的,是初始化的过程
if i != 0:
tempcost += minsec if (j == min_color) else minn
# 如果小于最小值,更新最小值和下标,并把最小值变为第二小值
if tempcost < tempmin:
tempminsec = tempmin
tempmin = tempcost
tempcolor = j
# 如果小于第二小值,那么更新第二小值
elif tempcost < tempminsec:
tempminsec = tempcost
# i房子遍历完,更新
minn = tempmin
min_color = tempcolor
minsec = tempminsec
# 最后返回minn即可。
return minn
# 266
class Solution:
def canPermutePalindrome(self, s: str) -> bool:
tmp = Counter(s)
count = 0
for i in tmp.items():
if i[1] % 2 != 0:
count += 1
return count <= 1
# 267
class Solution:
def generatePalindromes(self, s: str) -> List[str]:
n = len(s)
char_freq = defaultdict(int)
for c in s:
char_freq[c] += 1
odd_cnt = 0 #出现频率为奇数的字母个数
odd_char = '#' #频率为奇数次的那个字母
for c in char_freq.keys():
if char_freq[c] % 2 == 1:
odd_cnt += 1
odd_char = c
if odd_cnt > 1: #只允许有一个出现奇数次的字母
return []
mid = ""
if odd_cnt == 1: #如果有一个出现奇数次的字母
mid += odd_char
char_freq[odd_char] -= 1
self.res = []
def dfs_backtrace(cur: str, target_len: int) -> None:
if len(cur) > target_len:
return
if len(cur) == target_len:
self.res.append(cur[:])
for c,freq in char_freq.items():
if freq > 0:
char_freq[c] -= 2
dfs_backtrace(c + cur + c, target_len)
char_freq[c] += 2 #回溯 套路
dfs_backtrace(mid, n)
return self.res
# 268
class Solution:
def missingNumber(self, nums: List[int]) -> int:
n = len(nums)
return n * (n + 1) // 2 - sum(nums)
# 269 (真的不会0 0)
# 270
class Solution:
def closestValue(self, root: TreeNode, target: float) -> int:
res = root.val
while root:
res = root.val if abs(root.val - target) < abs(res - target) else res
if root.val < target:
root = root.right
else:
root = root.left
return res