二、中等

339、嵌套列表权重和

给定一个嵌套的整数列表 nestedList ,每个元素要么是整数,要么是列表。同时,列表中元素同样也可以是整数或者是另一个列表。

整数的 深度 是其在列表内部的嵌套层数。例如,嵌套列表 [1,[2,2],[[3],2],1] 中每个整数的值就是其深度。

请返回该列表按深度加权后所有整数的总和。

链接:https://leetcode.cn/problems/nested-list-weight-sum
# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger:
#    def __init__(self, value=None):
#        """
#        If value is not specified, initializes an empty list.
#        Otherwise initializes a single integer equal to value.
#        """
#
#    def isInteger(self):
#        """
#        @return True if this NestedInteger holds a single integer, rather than a nested list.
#        :rtype bool
#        """
#
#    def add(self, elem):
#        """
#        Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
#        :rtype void
#        """
#
#    def setInteger(self, value):
#        """
#        Set this NestedInteger to hold a single integer equal to value.
#        :rtype void
#        """
#
#    def getInteger(self):
#        """
#        @return the single integer that this NestedInteger holds, if it holds a single integer
#        Return None if this NestedInteger holds a nested list
#        :rtype int
#        """
#
#    def getList(self):
#        """
#        @return the nested list that this NestedInteger holds, if it holds a nested list
#        Return None if this NestedInteger holds a single integer
#        :rtype List[NestedInteger]
#        """
class Solution:def depthSum(self, nestedList: List[NestedInteger]) -> int:dic1 = []dic2 = []def dfs(l, depth):for x in l:if x.isInteger():dic1.append(x.getInteger())dic2.append(depth)else:dfs(x.getList(), depth+1)dfs(nestedList, 1)ans = 0for x, y in zip(dic1, dic2):ans += (x*y)return ans

348、设计井字棋

请在 n × n 的棋盘上,实现一个判定井字棋(Tic-Tac-Toe)胜负的神器,判断每一次玩家落子后,是否有胜出的玩家。

在这个井字棋游戏中,会有 2 名玩家,他们将轮流在棋盘上放置自己的棋子。

在实现这个判定器的过程中,你可以假设以下这些规则一定成立:

  1. 每一步棋都是在棋盘内的,并且只能被放置在一个空的格子里;2. 一旦游戏中有一名玩家胜出的话,游戏将不能再继续;3. 一个玩家如果在同一行、同一列或者同一斜对角线上都放置了自己的棋子,那么他便获得胜利。链接:https://leetcode.cn/problems/design-tic-tac-toe
class TicTacToe:def __init__(self, n: int):# inf = 2*31 - 1self.keyboard = [['' for _ in range(n)] for _ in range(n)]self.n = nself.dic1_r = defaultdict(int)self.dic1_c = defaultdict(int)self.dic1_w = 0self.dic1_u = 0self.dic2_r = defaultdict(int)self.dic2_c = defaultdict(int)self.dic2_w = 0self.dic2_u = 0def move(self, row: int, col: int, player: int) -> int:if player == 1:self.keyboard[row][col] = 'X'self.dic1_r[row] += 1self.dic1_c[col] += 1if row == col:self.dic1_w+=1if row == self.n-col-1:self.dic1_u+=1if self.dic1_r[row] == self.n or self.dic1_c[col] == self.n:return 1if self.dic1_w==self.n or self.dic1_u == self.n:return 1return 0else:self.keyboard[row][col] = 'O'self.dic2_r[row] += 1self.dic2_c[col] += 1if row == col:self.dic2_w+=1if row == self.n-col-1:self.dic2_u+=1if self.dic2_r[row] == self.n or self.dic2_c[col] == self.n:return 2if self.dic2_w==self.n or self.dic2_u == self.n:return 2return 0return 0# Your TicTacToe object will be instantiated and called as such:
# obj = TicTacToe(n)
# param_1 = obj.move(row,col,player)

360、有序转化数组

给你一个已经 排好序 的整数数组 nums 和整数 a 、 b 、 c 。对于数组中的每一个元素 nums[i] ,计算函数值 f(x) = ax2 + bx + c ,请 按升序返回数组 。

链接:https://leetcode.cn/problems/sort-transformed-array
class Solution:def sortTransformedArray(self, nums: List[int], a: int, b: int, c: int) -> List[int]:ans = []### 一元一次方程if a == 0:for i,x in enumerate(nums):tmp = a*(x**2) + b*x + cans.append(tmp)if b>0:return ans### 常数elif b==0:return [c]*len(nums)else:return ans[::-1]l = -(b/(2*a))idx = -1minm = float("inf")for i,x in enumerate(nums):if abs(x-l) < minm:idx = iminm = abs(x-l)left, right = idx-1, idx+1while left >= 0 and right <= len(nums)-1:tmp = a*(nums[idx]**2) + b*nums[idx] + cans.append(tmp)if abs(nums[left]-l) > abs(nums[right]-l):idx = rightright += 1else:idx = leftleft -= 1tmp = a*(nums[idx]**2) + b*nums[idx] + cans.append(tmp)if left != -1:for i in range(left,-1,-1):tmp = a*(nums[i]**2) + b*nums[i] + cans.append(tmp)if right != len(nums) :for i in range(right, len(nums)):tmp = a*(nums[i]**2) + b*nums[i] + cans.append(tmp)if a>0:return anselse:return ans[::-1]

362、敲击计数器

设计一个敲击计数器,使它可以统计在过去 5 分钟内被敲击次数。(即过去 300 秒)

您的系统应该接受一个时间戳参数 timestamp (单位为 秒 ),并且您可以假定对系统的调用是按时间顺序进行的(即 timestamp 是单调递增的)。几次撞击可能同时发生。

实现 HitCounter 类:

HitCounter() 初始化命中计数器系统。
void hit(int timestamp) 记录在 timestamp ( 单位为秒 )发生的一次命中。在同一个 timestamp 中可能会出现几个点击。
int getHits(int timestamp) 返回 timestamp 在过去 5 分钟内(即过去 300 秒)的命中次数。

链接:https://leetcode.cn/problems/design-hit-counter

class HitCounter:def __init__(self):self.times = defaultdict(int)self.time = []self.left = 0self.right = 0def hit(self, timestamp: int) -> None:if timestamp not in self.time:self.time.append(timestamp)while timestamp - self.time[self.left] >= 300:self.left += 1self.times[timestamp] += 1def getHits(self, timestamp: int) -> int:print(self.left, self.time)if timestamp not in self.time:while self.left<len(self.time) and timestamp - self.time[self.left] >= 300:self.left += 1ans = 0for i in range(self.left, len(self.time)):ans += self.times[self.time[i]]return ans# Your HitCounter object will be instantiated and called as such:
# obj = HitCounter()
# obj.hit(timestamp)
# param_2 = obj.getHits(timestamp)

361、轰炸敌人

给你一个大小为 m x n 的矩阵 grid ,其中每个单元格都放置有一个字符:

'W' 表示一堵墙
'E' 表示一个敌人
'0'(数字 0)表示一个空位

返回你使用 一颗炸弹 可以击杀的最大敌人数目。你只能把炸弹放在一个空位里。

由于炸弹的威力不足以穿透墙体,炸弹只能击杀同一行和同一列没被墙体挡住的敌人。

链接:https://leetcode.cn/problems/bomb-enemy
class Solution:def maxKilledEnemies(self, grid: List[List[str]]) -> int:m, n = len(grid), len(grid[0])self.res = 0### 超时# for i in range(m):#     for j in range(n):#         if grid[i][j] == '0':#             pathway = [(1,0),(0,1),(-1,0),(0,-1)]#             num = 0#             for k in range(4):#                 dr, dc = pathway[k]#                 nr, nc = i+dr, j+dc#                 while 0<=nr<m and 0<=nc<n and grid[nr][nc]!='W':#                     if grid[nr][nc] == 'E':#                         num+=1#                     nr += dr#                     nc += dc#             self.res = max(self.res, num)# return self.resf_r = [[-1 for _ in range(n)] for _ in range(m)]f_c = [[-1 for _ in range(n)] for _ in range(m)]for i in range(m):for j in range(n):if grid[i][j] == '0':if i==0 or f_r[i-1][j]==-1:pathway = [(1,0),(-1,0)]num = 0for k in range(2):dr, dc = pathway[k]nr, nc = i+dr, j+dcwhile 0<=nr<m and 0<=nc<n and grid[nr][nc]!='W':if grid[nr][nc] == 'E':num+=1nr += drnc += dcf_r[i][j] = numelse:f_r[i][j] = f_r[i-1][j]if j==0 or f_c[i][j-1] == -1:pathway = [(0,1),(0,-1)]num = 0for k in range(2):dr, dc = pathway[k]nr, nc = i+dr, j+dcwhile 0<=nr<m and 0<=nc<n and grid[nr][nc]!='W':if grid[nr][nc] == 'E':num+=1nr += drnc += dcf_c[i][j] = numelse:f_c[i][j] = f_c[i][j-1]self.res = max(self.res, f_r[i][j]+f_c[i][j])return self.res

364、加权嵌套序列和二

给你一个整数嵌套列表 nestedList ,每一个元素要么是一个整数,要么是一个列表(这个列表中的每个元素也同样是整数或列表)。

整数的 深度 取决于它位于多少个列表内部。例如,嵌套列表 [1,[2,2],[[3],2],1] 的每个整数的值都等于它的 深度 。令 maxDepth 是任意整数的 最大深度 。
整数的 权重 为 maxDepth - (整数的深度) + 1 。
将 nestedList 列表中每个整数先乘权重再求和,返回该加权和。

链接:https://leetcode.cn/problems/nested-list-weight-sum-ii

# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger:
#    def __init__(self, value=None):
#        """
#        If value is not specified, initializes an empty list.
#        Otherwise initializes a single integer equal to value.
#        """
#
#    def isInteger(self):
#        """
#        @return True if this NestedInteger holds a single integer, rather than a nested list.
#        :rtype bool
#        """
#
#    def add(self, elem):
#        """
#        Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
#        :rtype void
#        """
#
#    def setInteger(self, value):
#        """
#        Set this NestedInteger to hold a single integer equal to value.
#        :rtype void
#        """
#
#    def getInteger(self):
#        """
#        @return the single integer that this NestedInteger holds, if it holds a single integer
#        Return None if this NestedInteger holds a nested list
#        :rtype int
#        """
#
#    def getList(self):
#        """
#        @return the nested list that this NestedInteger holds, if it holds a nested list
#        Return None if this NestedInteger holds a single integer
#        :rtype List[NestedInteger]
#        """
class Solution:def depthSumInverse(self, nestedList: List[NestedInteger]) -> int:self.depth = []self.nums = []def dfs(i, x, dist):l = x.getList()for j,y in enumerate(l):if y.isInteger():self.depth.append(dist)self.nums.append(y.getInteger())elif y.getList() == []:self.depth.append(dist)self.nums.append(0)else:dfs(i+j, y, dist+1)for i,x in enumerate(nestedList):dp = 1if not x.isInteger():# if x.getList() != []:dfs(i, x, dp+1)else:self.depth.append(dp)self.nums.append(x.getInteger())if self.depth == []: return 0max_depth = max(self.depth)res = 0for i in range(len(self.depth)):res += (max_depth-self.depth[i]+1)*self.nums[i]print(self.depth, self.nums)return res

379、电话目录管理系统

设计一个电话目录管理系统,让它支持以下功能:

get: 分配给用户一个未被使用的电话号码,获取失败请返回 -1 check: 检查指定的电话号码是否被使用 release:
释放掉一个电话号码,使其能够重新被分配

链接:https://leetcode.cn/problems/design-phone-directory
class PhoneDirectory:def __init__(self, maxNumbers: int):self.dic = defaultdict(int)for i in range(maxNumbers):self.dic[i] = 0def get(self) -> int:for k, v in self.dic.items():if v == 0: self.dic[k] = 1return kreturn -1def check(self, number: int) -> bool:if self.dic[number]==0:return Trueelse:return Falsedef release(self, number: int) -> None:self.dic[number] = 0# Your PhoneDirectory object will be instantiated and called as such:
# obj = PhoneDirectory(maxNumbers)
# param_1 = obj.get()
# param_2 = obj.check(number)
# obj.release(number)

356、直线镜像

在一个二维平面空间中,给你 n 个点的坐标。问,是否能找出一条平行于 y 轴的直线,让这些点关于这条直线成镜像排布?

注意:题目数据中可能有重复的点。
class Solution:def isReflected(self, points: List[List[int]]) -> bool:def sorted_cmp(l1, l2):if l1[0] > l2[0]:return 1elif l1[0] == l2[0]:if l1[1] > l2[1]:return 1else:return -1else:return -1points.sort(key = cmp_to_key(sorted_cmp))arr = []for k in points:if k not in arr:arr.append(k)points = arrif len(points)%2 == 0:x = 0for l in points:x += l[0]x = x/len(points)i, j = 0, len(points)//2flag = Truewhile i < (len(points)//2) and j < (len(points)):# print(i, j, points, x)if points[i][0] == points[j][0] == x:flag = Trueelif points[i][1] != points[j][1] or x-points[i][0] != points[j][0]-x:flag = Falsebreaki+=1j+=1if flag:return Trueflag = Truei, j = 0, len(points)-1while i < (len(points)//2) and j > (len(points)//2 -1):# print(flag, points, x)if points[i][0] == points[j][0] == x:flag = Trueelif points[i][1] != points[j][1] or x-points[i][0] != points[j][0]-x:flag = Falsebreaki+=1j-=1if flag:return Truereturn Falseelse:x = points[len(points)//2][0]i, j = 0, len(points)//2+1flag = Truewhile i < (len(points)//2) and j < (len(points)):if points[i][0] == points[j][0] == x:flag = Trueelif points[i][1] != points[j][1] or x-points[i][0] != points[j][0]-x:flag = Falsebreaki+=1j+=1if flag:return Trueflag = Truei, j = 0, len(points)-1while i < (len(points)//2) and j > (len(points)//2):if points[i][0] == points[j][0] == x:flag = Trueelif points[i][1] != points[j][1] or x-points[i][0] != points[j][0]-x:flag = Falsebreaki+=1j-=1if flag:return Truereturn False

351、安卓系统手势解锁

class Solution:def numberOfPatterns(self, m: int, n: int) -> int:dic = {1 : {3,7,9},2 : {8},3 : {1,9,7},4 : {6},5 : {},6 : {4},7 : {1, 9, 3},8 : {2},9 : {3, 7, 1}}self.res = 0visited = [False for _ in range(9)]def check(arr):if len(arr) == 1:return Truefor i in range(0,len(arr)-1):x = arr[i]y = arr[i+1]if y in dic[x]:mid = (x + y)//2if mid not in arr[:i]:return Falsereturn Truedef backtrace(x, path):if x>=n+1:returnif not check(path):returnif x>=m and x<=n:self.res += 1for i in range(9):if not visited[i]:visited[i] = Truebacktrace(x+1, path+[i+1])visited[i] = Falsefor i in range(9):visited[i] = Truebacktrace(1, [i+1])visited[i] = Falsereturn self.res

549、二叉树中最长的连续序列

给定二叉树的根 root ,返回树中最长连续路径的长度。
连续路径是路径中相邻节点的值相差 1 的路径。此路径可以是增加或减少。

例如, [1,2,3,4] 和 [4,3,2,1] 都被认为有效,但路径 [1,2,4,3] 无效。
另一方面,路径可以是子-父-子顺序,不一定是父子顺序。

链接:https://leetcode.cn/problems/binary-tree-longest-consecutive-sequence-ii

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def longestConsecutive(self, root: Optional[TreeNode]) -> int:if not root: return 0self.res = 1def dfs(root):if not root: return (0, 0)left, right = dfs(root.left), dfs(root.right)inc = dec = 1if root.left:if root.left.val == root.val + 1:inc += left[0]elif root.left.val == root.val - 1:dec += left[1]if root.right:if root.right.val == root.val + 1:inc = max(inc, right[0] + 1)elif root.right.val == root.val - 1:dec = max(dec, right[1] + 1)self.res = max(self.res, inc + dec - 1)return (inc, dec)dfs(root)return self.res

510、二叉搜索树中的中序后继

给定一棵二叉搜索树和其中的一个节点 node ,找到该节点在树中的中序后继。如果节点没有中序后继,请返回 null 。

一个节点 node 的中序后继是键值比 node.val 大所有的节点中键值最小的那个。

你可以直接访问结点,但无法直接访问树。每个节点都会有其父节点的引用。节点 Node 定义如下:

class Node {public int val;public Node left;public Node right;public Node parent;
}

链接:https://leetcode.cn/problems/inorder-successor-in-bst-ii

"""
# Definition for a Node.
class Node:def __init__(self, val):self.val = valself.left = Noneself.right = Noneself.parent = None
"""class Solution:def inorderSuccessor(self, node: 'Node') -> 'Optional[Node]':###两种情况if node.right:node = node.rightwhile node.left:node = node.leftreturn nodewhile node.parent and node == node.parent.right:node = node.parentreturn node.parent

487、最大连续1的个数二

给定一个二进制数组 nums ,如果最多可以翻转一个 0 ,则返回数组中连续 1 的最大个数。

class Solution:def findMaxConsecutiveOnes(self, nums: List[int]) -> int:f = [[0,0] for _ in range(len(nums))]if nums[0] == 1:f[0][1] = 1f[0][0] = 0else:f[0][1] = 0f[0][0] = 1idx = 1res = 1while idx < len(nums):if nums[idx]==1:f[idx][0] = f[idx-1][0] + 1f[idx][1] = f[idx-1][1] + 1if nums[idx] == 0:f[idx][0] = f[idx-1][1] + 1f[idx][1] = 0res = max(res,f[idx][0],f[idx][1])idx += 1return res

439、三元表达式解析器

给定一个表示任意嵌套三元表达式的字符串 expression ,求值并返回其结果。

你可以总是假设给定的表达式是有效的,并且只包含数字, ‘?’ , ‘:’ , ‘T’ 和 ‘F’ ,其中 ‘T’ 为真, ‘F’ 为假。表达式中的所有数字都是 一位 数(即在 [0,9] 范围内)。

条件表达式从右到左分组(大多数语言中都是这样),表达式的结果总是为数字 ‘T’ 或 ‘F’ 。

链接:https://leetcode.cn/problems/ternary-expression-parser

class Solution:def parseTernary(self, expression: str) -> str:st = []is_flag = Falsefor i in range(len(expression)-1, -1, -1):if expression[i] == ':':continueelif expression[i] == '?':is_flag = Trueelse:if is_flag:if expression[i] == 'T':res = st[-1]st.pop()st.pop()st.append(res)else:st.pop()is_flag = Falseelse:st.append(expression[i])return st[0]

544、输出比赛匹配对

在 NBA 季后赛中,我们总是安排较强的队伍对战较弱的队伍,例如用排名第 1 的队伍和第 n 的队伍对决,这是一个可以让比赛更加有趣的好策略。现在,给你 n 支队伍,你需要以字符串格式输出它们的 最终 比赛配对。

n 支队伍按从 1 到 n 的正整数格式给出,分别代表它们的初始排名(排名 1 最强,排名 n 最弱)。我们用括号(‘(’, ‘)’)和逗号(‘,’)来表示匹配对——括号(‘(’, ‘)’)表示匹配,逗号(‘,’)来用于分割。 在每一轮的匹配过程中,你都需要遵循将强队与弱队配对的原则。

链接:https://leetcode.cn/problems/output-contest-matches

class Solution(object):def findContestMatch(self, n):team = [str(x) for x in range(1, n + 1)]while n > 1:for i in range(n // 2):team[i] = "({},{})".format(team[i], team[n-i-1])n //= 2return team[0]

484、寻找排列

由范围 [1,n] 内所有整数组成的 n 个整数的排列 perm 可以表示为长度为 n - 1 的字符串 s ,其中:

如果 perm[i] < perm[i + 1] ,那么 s[i] == ’ i ’
如果 perm[i] > perm[i + 1] ,那么 s[i] == ‘D’ 。
给定一个字符串 s ,重构字典序上最小的排列 perm 并返回它。

链接:https://leetcode.cn/problems/find-permutation

class Solution:def findPermutation(self, s: str) -> List[int]:### DFS# n = len(s) + 1# self.res = []# visited = [False for _ in range(n)]# def dfs(arr, idx):#     if self.res != []:#         return#     if len(arr)==n:#         self.res = (arr)#         return#     if idx >= n-1:#         return#     for x in range(1,n+1):#         if s[idx] == 'I' and not visited[x-1] and x>(arr[-1]):#             visited[x-1] = True#             dfs(arr+[(x)], idx+1)#             visited[x-1] = False#         if s[idx] == 'D' and not visited[x-1] and x<(arr[-1]):#             visited[x-1] = True#             dfs(arr+[(x)], idx+1)#             visited[x-1] = False# for i in range(1, n+1):#     visited[i-1] = True#     dfs([(i)], 0)#     if self.res != []:#         break#     visited[i-1] = False# return (self.res)### dp 不超时n = len(s) nums = list(range(1, n+2))pre = s[0]cnt = 1for i in range(1, n):if pre == s[i]:cnt += 1else:if pre == 'D':nums[i-cnt:i+1] = nums[i-cnt:i+1][::-1]pre = s[i]cnt = 1if pre == 'D':nums[n-cnt:n+1] = nums[n-cnt:n+1][::-1]return nums

555、分割连接字符串

给定一个字符串列表 strs,你可以将这些字符串连接成一个循环字符串,对于每个字符串,你可以选择是否翻转它。在所有可能的循环字符串中,你需要分割循环字符串(这将使循环字符串变成一个常规的字符串),然后找到字典序最大的字符串。

具体来说,要找到字典序最大的字符串,你需要经历两个阶段:

将所有字符串连接成一个循环字符串,你可以选择是否翻转某些字符串,并按照给定的顺序连接它们。
在循环字符串的某个位置分割它,这将使循环字符串从分割点变成一个常规的字符串。
你的工作是在所有可能的常规字符串中找到字典序最大的一个。

链接:https://leetcode.cn/problems/split-concatenated-strings

class Solution:def splitLoopedString(self, strs: List[str]) -> str:### Limted time exceed# arr = []# res = ''# for s in strs:#     tmp = arr#     arr = []#     s1 = s#     s2 = s[::-1]#     if tmp == []:#         arr = [s1,s2]#     else:#         for x in tmp:#             arr.append(x+s1)#             arr.append(x+s2)# for x in arr:#     for i in range(len(x)):#         res = max(res, x[i:] + x[:i])# return (res)####arr = [s if s>s[::-1] else s[::-1] for s in strs]res = ''.join(arr)for i in range(len(arr)):other =  ''.join(arr[i+1:]) + ''.join(arr[:i])for j in range(len(arr[i])):head = arr[i][:j]tail = arr[i][j:]cur = tail + other + headres = max(cur, res)cur = head[::-1] + other + tail[::-1]res = max(cur, res)return res

573、松鼠模拟

现在有一棵树,一只松鼠和一些坚果。位置由二维网格的单元格表示。你的目标是找到松鼠收集所有坚果的最小路程,且坚果是一颗接一颗地被放在树下。松鼠一次最多只能携带一颗坚果,松鼠可以向上,向下,向左和向右四个方向移动到相邻的单元格。移动次数表示路程。

链接:https://leetcode.cn/problems/squirrel-simulation

class Solution:def minDistance(self, height: int, width: int, tree: List[int], squirrel: List[int], nuts: List[List[int]]) -> int:path = float('inf')x, y = squirrelx_t, y_t = treepath_t = 0for i, j in nuts:cur = abs(i-x_t) + abs(j-y_t)path_t += cur*2for i,j in nuts:cur = path_t - (abs(i-x_t) + abs(j-y_t)) + (abs(i-x) + abs(j-y))path = min(path, cur)return path

634、寻找数组的错位排序

在组合数学中,如果一个排列中所有元素都不在原先的位置上,那么这个排列就被称为 错位排列 。

给定一个从 1 到 n 升序排列的数组,返回 不同的错位排列 的数量 。由于答案可能非常大,你只需要将答案对 109+7 取余 输出即可。

链接:https://leetcode.cn/problems/find-the-derangement-of-an-array

class Solution:def findDerangement(self, n: int) -> int:f = [0 for _ in range(n+1)]f[0] = 0f[1] = 1for i in range(2, n+1):f[i] = (i)*(f[i-1] + f[i-2]) % 1000000007return f[n-1]

1057、校园自行车分配

在 X-Y 平面上表示的校园中,有 n 名工人和 m 辆自行车,其中 n <= m。

给定一个长度为 n 的数组 workers ,其中 worker [i] = [xi, yi] 表示第 i 个工人的位置。你也得到一个长度为 m 的自行车数组 bikers ,其中 bikes[j] = [xj, yj] 是第 j 辆自行车的位置。所有给定的位置都是 唯一 的。

我们需要为每位工人分配一辆自行车。在所有可用的自行车和工人中,我们选取彼此之间 曼哈顿距离 最短的工人自行车对 (workeri, bikej) ,并将其中的自行车分配給工人。

如果有多个 (workeri, bikej) 对之间的 曼哈顿距离 相同,那么我们选择 工人索引最小 的那对。类似地,如果有多种不同的分配方法,则选择 自行车索引最小 的一对。不断重复这一过程,直到所有工人都分配到自行车为止。

返回长度为 n 的向量 answer,其中 answer[i] 是第 i 位工人分配到的自行车的索引(从 0 开始)。

给定两点 p1 和 p2 之间的 曼哈顿距离 为 Manhattan(p1, p2) = |p1.x - p2.x| + |p1.y - p2.y|。

链接:https://leetcode.cn/problems/campus-bikes
class Solution:def assignBikes(self, workers: List[List[int]], bikes: List[List[int]]) -> List[int]:def Manhattan(p1, p2):return abs(p1[0]-p2[0])+abs(p1[1]-p2[1])from sortedcontainers import SortedDict as SDdic = SD()for i,b in enumerate(workers):for j,w in enumerate(bikes):dist = Manhattan(b, w)if dist not in dic:dic[dist] = [(i,j)]else:dic[dist].append((i, j))res = [0 for _ in range(len(workers))]visited_b = [False for _ in range(len(bikes))]visited_w = [False for _ in range(len(workers))]cnt = 0for k, v in dic.items():for x in v:i, j = xif not visited_w[i] and not visited_b[j]:visited_w[i] = Truevisited_b[j] = Trueres[i] = jcnt+=1if cnt == len(workers):breakreturn res

505、迷宫二

由空地和墙组成的迷宫中有一个球。球可以向上下左右四个方向滚动,但在遇到墙壁前不会停止滚动。当球停下时,可以选择下一个方向。

给定球的起始位置,目的地和迷宫,找出让球停在目的地的最短距离。距离的定义是球从起始位置(不包括)到目的地(包括)经过的空地个数。如果球无法停在目的地,返回 -1。

迷宫由一个0和1的二维数组表示。 1表示墙壁,0表示空地。你可以假定迷宫的边缘都是墙壁。起始位置和目的地的坐标通过行号和列号给出。

链接:https://leetcode.cn/problems/the-maze-ii

class Solution:def shortestDistance(self, maze: List[List[int]], start: List[int], destination: List[int]) -> int:queue = [(start[0], start[1])]m, n = len(maze), len(maze[0])dist = [[float('inf') for _ in range(n)]for _ in range(m)]dist[start[0]][start[1]] = 0while queue:cur_i, cur_j = queue.pop(0)print(cur_i, cur_j)pathway = [(1,0),(-1,0),(0,1),(0,-1)]for i in range(4):dr, dc = pathway[i]nr, nc = cur_i+dr, cur_j+dcstep = 1while 0<=nr<m and 0<=nc<n and maze[nr][nc]==0:nr += drnc += dcstep += 1nr -= drnc -= dcstep -= 1if dist[nr][nc]>dist[cur_i][cur_j]+step:dist[nr][nc] = dist[cur_i][cur_j]+stepqueue.append((nr, nc))if dist[destination[0]][destination[1]] == float('inf'):return -1else:return dist[destination[0]][destination[1]]

533、孤独像素二

给你一个大小为 m x n 的二维字符数组 picture ,表示一张黑白图像,数组中的 ‘B’ 表示黑色像素,‘W’ 表示白色像素。另给你一个整数 target ,请你找出并返回符合规则的 黑色 孤独像素的数量。

黑色孤独像素是指位于某一特定位置 (r, c) 的字符 ‘B’ ,其中:

行 r 和列 c 中的黑色像素恰好有 target 个。
列 c 中所有黑色像素所在的行必须和行 r 完全相同。

链接:https://leetcode.cn/problems/lonely-pixel-ii

class Solution:def findBlackPixel(self, picture: List[List[str]], target: int) -> int:m, n = len(picture), len(picture[0])dic_r = defaultdict(list)dic_c = defaultdict(list)for i in range(m):for j in range(n):if picture[i][j] == 'B':dic_r[i].append(j)dic_c[j].append(i)res = 0# print(dic_r, dic_c)for i in range(m):if len(dic_r[i])!=target:continuefor j in range(n):if len(dic_c[j])!=target:continueif picture[i][j]== 'B':y = dic_r[i]flag = Truefor x in dic_c[j]:if dic_r[x] != y:flag = Falsebreakif flag: res+=1return res

635、设计日志存储系统

你将获得多条日志,每条日志都有唯一的 id 和 timestamp ,timestamp 是形如 Year:Month:Day:Hour:Minute:Second 的字符串,2017:01:01:23:59:59 ,所有值域都是零填充的十进制数。

实现 LogSystem 类:

LogSystem() 初始化 LogSystem 对象
void put(int id, string timestamp) 给定日志的 id 和 timestamp ,将这个日志存入你的存储系统中。
int[] retrieve(string start, string end, string granularity) 返回在给定时间区间 [start, end] (包含两端)内的所有日志的 id 。start 、end 和 timestamp 的格式相同,granularity 表示考虑的时间粒度(例如,精确到 Day、Minute 等)。例如 start = "2017:01:01:23:59:59"、end = "2017:01:02:23:59:59" 且 granularity = "Day" 意味着需要查找从 Jan. 1st 2017 到 Jan. 2nd 2017 范围内的日志,可以忽略日志的 Hour、Minute 和 Second 。

链接:https://leetcode.cn/problems/design-log-storage-system

class LogSystem:def __init__(self):self.dict = defaultdict(str)self.granularity_dict = {"Year": 4, "Month": 7, "Day": 10,"Hour": 13, "Minute": 16, "Second": 19}def put(self, id: int, timestamp: str) -> None:self.dict[id] = timestampdef retrieve(self, start: str, end: str, granularity: str) -> List[int]:check_len = self.granularity_dict[granularity]res = []for key, val in self.dict.items():if val[:check_len] >= start[:check_len] and val[:check_len] <= end[:check_len]:res.append(key)return res

545、二叉树的边界

二叉树的 边界 是由 根节点 、左边界 、按从左到右顺序的 叶节点 和 逆序的右边界 ,按顺序依次连接组成。

左边界 是满足下述定义的节点集合:

根节点的左子节点在左边界中。如果根节点不含左子节点,那么左边界就为 空 。
如果一个节点在左边界中,并且该节点有左子节点,那么它的左子节点也在左边界中。
如果一个节点在左边界中,并且该节点 不含 左子节点,那么它的右子节点就在左边界中。
最左侧的叶节点 不在 左边界中。
右边界 定义方式与 左边界 相同,只是将左替换成右。即,右边界是根节点右子树的右侧部分;叶节点 不是 右边界的组成部分;如果根节点不含右子节点,那么右边界为 空 。

叶节点 是没有任何子节点的节点。对于此问题,根节点 不是 叶节点。

给你一棵二叉树的根节点 root ,按顺序返回组成二叉树 边界 的这些值。

链接:https://leetcode.cn/problems/boundary-of-binary-tree

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def boundaryOfBinaryTree(self, root: Optional[TreeNode]) -> List[int]:if root and not root.left and not root.right:return [root.val]left = []bottom = []right = []def leftdfs(root):if root and (root.left or root.right):left.append(root.val)if root.left:leftdfs(root.left)else:leftdfs(root.right)def bottomdfs(root):if not root: returnif not root.left and not root.right:bottom.append(root.val)returnbottomdfs(root.left)bottomdfs(root.right)def rightdfs(root):if root and (root.left or root.right):right.append(root.val)if root.right:rightdfs(root.right)else:rightdfs(root.left)leftdfs(root.left)bottomdfs(root)rightdfs(root.right)return [root.val] + left + bottom + right[::-1]

616、给字符串添加加粗字符串

给你一个字符串 s 和一个字符串列表 words ,你需要将在字符串列表中出现过的 s 的子串添加加粗闭合标签

如果两个子串有重叠部分,你需要把它们一起用一对闭合标签包围起来。同理,如果两个子字符串连续被加粗,那么你也需要把它们合起来用一对加粗标签包围。

返回添加加粗标签后的字符串 s 。

链接:https://leetcode.cn/problems/add-bold-tag-in-string

class Solution:def addBoldTag(self, s: str, words: List[str]) -> str:n = len(s)mask = [False for _ in range(n)]for i in range(n):for word in words:if i+len(word)<=n and s[i:i+len(word)]==word:for j in range(i, i+len(word)):mask[j] = Trueres = ''for i in range(n):if mask[i] and (i==0 or mask[i-1]==False):res+='<b>'res+=s[i]if mask[i] and (i==n-1 or mask[i+1]==False):res+='</b>'return res

624、数组列表中的最大距离

给定 m 个数组,每个数组都已经按照升序排好序了。现在你需要从两个不同的数组中选择两个整数(每个数组选一个)并且计算它们的距离。两个整数 a 和 b 之间的距离定义为它们差的绝对值 |a-b| 。你的任务就是去找到最大距离

链接:https://leetcode.cn/problems/maximum-distance-in-arrays
class Solution:def maxDistance(self, arrays: List[List[int]]) -> int:m = len(arrays)res = -float('inf')arr = []for i in range(m):if len(arrays[i]) == 1 or arrays[i][0]==arrays[i][-1]:arr.append((arrays[i][0], i))else:minn, maxn = arrays[i][0], arrays[i][-1]arr.append((minn, i))arr.append((maxn, i))arr.sort(key = lambda x:x[0])print(arr)if arr[0][1] == arr[-1][1]:res = max(abs(arr[-1][0]-arr[1][0]), abs(arr[-2][0]-arr[0][0]))else:res = arr[-1][0]-arr[0][0]return res

723、粉碎糖果

这个问题是实现一个简单的消除算法。

给定一个 m x n 的二维整数数组 board 代表糖果所在的方格,不同的正整数 board[i][j] 代表不同种类的糖果,如果 board[i][j] == 0 代表 (i, j) 这个位置是空的。

给定的方格是玩家移动后的游戏状态,现在需要你根据以下规则粉碎糖果,使得整个方格处于稳定状态并最终输出:

如果有三个及以上水平或者垂直相连的同种糖果,同一时间将它们粉碎,即将这些位置变成空的。
在同时粉碎掉这些糖果之后,如果有一个空的位置上方还有糖果,那么上方的糖果就会下落直到碰到下方的糖果或者底部,这些糖果都是同时下落,也不会有新的糖果从顶部出现并落下来。
通过前两步的操作,可能又会出现可以粉碎的糖果,请继续重复前面的操作。
当不存在可以粉碎的糖果,也就是状态稳定之后,请输出最终的状态。
你需要模拟上述规则并使整个方格达到稳定状态,并输出。

链接:https://leetcode.cn/problems/candy-crush

class Solution:def candyCrush(self, board: List[List[int]]) -> List[List[int]]:m, n = len(board), len(board[0])mask = [[False for _ in range(n)]for _ in range(m)]while 1:mask = [[False for _ in range(n)]for _ in range(m)]flag = Falsefor i in range(m):for j in range(n-2):if board[i][j]!=0 and board[i][j] == board[i][j+1] == board[i][j+2]:flag = Truemask[i][j] = mask[i][j+1] = mask[i][j+2] = Truefor i in range(n):for j in range(m-2):if board[j][i]!=0 and board[j][i] == board[j+1][i] == board[j+2][i]:flag = Truemask[j][i] = mask[j+1][i] = mask[j+2][i] = Trueif flag:for c in range(n):rr = m - 1for r in range(m - 1, -1, -1):if mask[r][c] == False:board[rr][c] = board[r][c]rr -= 1while rr > -1:board[rr][c] = 0rr -= 1else:breakreturn board

737、句子相似性二

并查集
我们可以将一个句子表示为一个单词数组,例如,句子 I am happy with leetcode"可以表示为 arr = [“I”,“am”,happy",“with”,“leetcode”]

给定两个句子 sentence1 和 sentence2 分别表示为一个字符串数组,并给定一个字符串对 similarPairs ,其中 similarPairs[i] = [xi, yi] 表示两个单词 xi 和 yi 是相似的。

如果 sentence1 和 sentence2 相似则返回 true ,如果不相似则返回 false 。

两个句子是相似的,如果:

  • 它们具有 相同的长度 (即相同的字数)
  • sentence1[i] 和 sentence2[i] 是相似的

请注意,一个词总是与它自己相似,也请注意,相似关系是可传递的。例如,如果单词 a 和 b 是相似的,单词 b 和 c 也是相似的,那么 a 和 c 也是 相似 的。

链接:https://leetcode.cn/problems/sentence-similarity-ii

class Union:def __init__(self, n):self.father = [i for i in range(n)]def findFather(self, x):while x != self.father[x]:self.father[x] = self.father[self.father[x]]x = self.father[x]return xdef union(self, x, y):fa_x = self.findFather(x)fa_y = self.findFather(y)if fa_x != fa_y:if fa_x < fa_y:fa_x, fa_y = fa_y, fa_xself.father[fa_y] = fa_xdef isConnect(self, x, y):fa_x = self.findFather(x)fa_y = self.findFather(y)return fa_x==fa_y
class Solution:def areSentencesSimilarTwo(self, sentence1: List[str], sentence2: List[str], similarPairs: List[List[str]]) -> bool:if len(sentence1) != len(sentence2): return Falsen = len(sentence1)sentence = sentence1 + sentence2dic = dict()Id = 0for x in sentence:if x not in dic:dic[x] = IdId += 1for x,y in similarPairs:if x not in dic:dic[x] = IdId += 1if y not in dic:dic[y] = IdId += 1uf = Union(Id)for x,y in similarPairs:uf.union(dic[x], dic[y])for i in range(n):if not uf.isConnect(dic[sentence1[i]], dic[sentence2[i]]):return Falsereturn True

651、四键键盘

假设你有一个特殊的键盘包含下面的按键:

A:在屏幕上打印一个 'A'。
Ctrl-A:选中整个屏幕。
Ctrl-C:复制选中区域到缓冲区。
Ctrl-V:将缓冲区内容输出到上次输入的结束位置,并显示在屏幕上。
现在,你可以 最多 按键 n 次(使用上述四种按键),返回屏幕上最多可以显示 'A' 的个数 。

链接:https://leetcode.cn/problems/4-keys-keyboard

class Solution:def maxA(self, n: int) -> int:#### dfs# self.res = 0# def dfs(cur_i, nums, tmp):#     if cur_i == n:#         self.res = max(self.res, nums)#         return #     pathway = [1,3,1]#     for i in range(3):#         di = pathway[i]#         if 0 <= cur_i+di <= n:#             ni = cur_i + di#             if i == 0:#                 dfs(ni, nums+1, tmp)#             elif i==1:#                 dfs(ni, nums*2, nums)#             elif i==2:#                 dfs(ni, nums+tmp, tmp)# dfs(0,0,0)# return self.res#### dpself.res = 0f = [0 for _ in range(n)]f[0] = 1for i in range(1, n):f[i] = f[i-1] + 1for j in range(i):f[i] = max(f[i], f[j]*(i-j-2+1))return (f[n-1])

663、均匀树划分

给定一棵有 n 个结点的二叉树,你的任务是检查是否可以通过去掉树上的一条边将树分成两棵,且这两棵树结点之和相等。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def checkEqualTree(self, root: Optional[TreeNode]) -> bool:def sumTree(root):if not root:return 0left = sumTree(root.left)right = sumTree(root.right)return root.val + left + rightsumm = sumTree(root)if summ % 2 != 0:return Falsetarget = summ//2def findtarget(root, pre):if not root:return Falseif pre and sumTree(root) == target:return Truereturn findtarget(root.left, root) or findtarget(root.right, root)return findtarget(root, None)

666、路经总和四

对于一棵深度小于 5 的树,可以用一组三位十进制整数来表示。对于每个整数:

百位上的数字表示这个节点的深度 d,1 <= d <= 4。
十位上的数字表示这个节点在当前层所在的位置 P, 1 <= p <= 8。位置编号与一棵满二叉树的位置编号相同。
个位上的数字表示这个节点的权值 v,0 <= v <= 9。
给定一个包含三位整数的 升序 数组 nums ,表示一棵深度小于 5 的二叉树,请你返回 从根到所有叶子结点的路径之和 。

保证 给定的数组表示一个有效的连接二叉树。

链接:https://leetcode.cn/problems/path-sum-iv

class Solution:def pathSum(self, nums: List[int]) -> int:def int2arr(x):arr = [int(str(x)[0]),int(str(x)[1]) ,int(str(x)[2])]return arrarr = []for x in nums:tmp = int2arr(x)arr.append(tmp)root = arr[0]st = [root]res = []while st:tmp = stst = []while tmp:depth, width, summ = tmp.pop(0)flag1, flag2=False, Falsefor d, w, n in arr:if d==depth+1 and w == width*2-1:st.append([d, w, summ+n])flag1=Truefor d, w, n in arr:if d==depth+1 and w == width*2:st.append([d, w, summ+n])flag1=Trueif not flag1 and not flag2:res.append(summ)return (sum(res))

1066、校园自行车

1120、子树的平均值

给你一棵二叉树的根节点 root,找出这棵树的 每一棵 子树的 平均值 中的 最大 值。
子树是树中的任意节点和它的所有后代构成的集合。
树的平均值是树中节点值的总和除以节点数。

链接:https://leetcode.cn/problems/maximum-average-subtree

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def maximumAverageSubtree(self, root: Optional[TreeNode]) -> float:def sumTree(root, nums):if not root:return 0, 0left, nums_l = sumTree(root.left, nums+1)right, nums_r = sumTree(root.right, nums+1)return root.val + left + right, nums_l+nums_r+1self.res = 0def dfs(root):if not root:returndfs(root.left)dfs(root.right)summ, nums = sumTree(root, 0)self.res = max(self.res, summ/nums)dfs(root)return self.res

1152、用户网站访问行为分析

给定两个字符串数组 username 和 website 和一个整数数组 timestamp 。给定的数组长度相同,其中元组 [username[i], website[i], timestamp[i]] 表示用户 username[i] 在时间 timestamp[i] 访问了网站 website[i] 。

访问模式 是包含三个网站的列表(不一定是完全不同的)。

例如,[“home”, “away”, “love”], [“leetcode”, “love”, “leetcode”],和 [“luffy”, “luffy”, “luffy”] 都是模式。
一种 访问模式 的 得分 是访问该模式中所有网站的用户数量,这些网站在该模式中出现的顺序相同。

例如,如果模式是 [“home”,“away”,“love”] ,那么分数就是用户数量 x , x 访问了 “home” ,然后访问了 “away” ,然后访问了 “love” 。
同样,如果模式是 [“leetcode”, “love”, “leetcode”] ,那么分数就是用户数量 x ,使得 x 访问了"leetcode",然后访问了 “love” ,之后又访问了 “leetcode” 。
另外,如果模式是 [“luffy”,“luffy”,“luffy”] ,那么分数就是用户数量 x ,这样 x 就可以在不同的时间戳上访问 “luffy” 三次。
返回 得分 最大的 访问模式 。如果有多个访问模式具有相同的最大分数,则返回字典序最小的。

链接:https://leetcode.cn/problems/analyze-user-website-visit-pattern

class Solution:def mostVisitedPattern(self, username: List[str], timestamp: List[int], website: List[str]) -> List[str]:dict_input = dict(zip(timestamp, zip(username, website)))dict_user = defaultdict(list)from sortedcontainers import SortedDict as SDmode = SD()print(sorted(dict_input.keys()))# for i in range(len(username)):for key in sorted(dict_input.keys()):user, web = dict_input[key]dict_user[user].append(web)for k,v in dict_user.items():if len(v)>=3:tmp_path_set = set() for i in range(len(v)-2):for j in range(i+1, len(v)-1):for z in range(j+1, len(v)):tmp_path_set.add(tuple([v[i],v[j],v[z]]))for p in tmp_path_set:if p not in mode:mode[p] = 0mode[p] += 1print(dict_user, mode)maxm = 0self.res = []for k,v in mode.items():if v>maxm:maxm = vself.res = list(k)return (self.res)

1166、设计文件系统

你需要设计一个文件系统,你可以创建新的路径并将它们与不同的值关联。

路径的格式是一个或多个连接在一起的字符串,形式为: / ,后面跟着一个或多个小写英文字母。例如, " /leetcode" 和 “/leetcode/problems” 是有效路径,而空字符串 “” 和 “/” 不是。

实现 FileSystem 类:

bool createPath(string path, int value) 创建一个新的 path ,并在可能的情况下关联一个 value ,然后返回 true 。如果路径已经存在或其父路径不存在,则返回 false 。
int get(string path) 返回与 path 关联的值,如果路径不存在则返回 -1 。

链接:https://leetcode.cn/problems/design-file-system

class FileSystem:def __init__(self):self.path_dict = defaultdict(int)def createPath(self, path: str, value: int) -> bool:if path == '' or path == '/':return Falsearr = path.split('/')[1:]if '/' in arr:return Falseif tuple(arr) in self.path_dict:return Falseelif len(arr)>1:if tuple(arr[:len(arr)-1]) not in self.path_dict:return Falseself.path_dict[tuple(arr)] = valuereturn Truedef get(self, path: str) -> int:arr = path.split('/')[1:]if tuple(arr) not in self.path_dict:return -1else:return self.path_dict[tuple(arr)]# Your FileSystem object will be instantiated and called as such:
# obj = FileSystem()
# param_1 = obj.createPath(path,value)
# param_2 = obj.get(path)

1167、连接棒材的最低费用

你有一些长度为正整数的棍子。这些长度以数组 sticks 的形式给出, sticks[i] 是 第i个 木棍的长度。

你可以通过支付 x + y 的成本将任意两个长度为 x 和 y 的棍子连接成一个棍子。你必须连接所有的棍子,直到剩下一个棍子。

返回以这种方式将所有给定的棍子连接成一个棍子的 最小成本 。

链接:https://leetcode.cn/problems/minimum-cost-to-connect-sticks

用heapq排序,每次取最小的两个,用sort会超时

class Solution:def connectSticks(self, sticks: List[int]) -> int:ans = 0heap = []for n in sticks:heapq.heappush(heap, n)while len(heap) >= 2:a = heapq.heappop(heap)b = heapq.heappop(heap)c = a + bans += cheapq.heappush(heap, c)return ans

1198、找出所有行的最小公共元素

利用set的特点

class Solution:def smallestCommonElement(self, mat: List[List[int]]) -> int:a = set(mat[0])for i in range(len(mat)):a = a & set(mat[i]) print(a)a = list(a)if len(a) == 0:return -1return a[0]

1214、查找两颗二叉树之和

给出两棵二叉搜索树的根节点 root1 和 root2 ,请你从两棵树中各找出一个节点,使得这两个节点的值之和等于目标值 Target。

如果可以找到返回 True,否则返回 False。

链接:https://leetcode.cn/problems/two-sum-bsts

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def twoSumBSTs(self, root1: Optional[TreeNode], root2: Optional[TreeNode], target: int) -> bool:self.res = []def dfs(root):if not root: returndfs(root.left)self.res.append(root.val)dfs(root.right)dfs(root1)res1 = self.res.copy()self.res = []dfs(root2)res2 = self.res.copy()for x in res1:if target - x in res2:return Truereturn False

1244、力扣排行榜

新一轮的「力扣杯」编程大赛即将启动,为了动态显示参赛者的得分数据,需要设计一个排行榜 Leaderboard。

请你帮忙来设计这个 Leaderboard 类,使得它有如下 3 个函数:

addScore(playerId, score):
假如参赛者已经在排行榜上,就给他的当前得分增加 score 点分值并更新排行。
假如该参赛者不在排行榜上,就把他添加到榜单上,并且将分数设置为 score。
top(K):返回前 K 名参赛者的 得分总和。
reset(playerId):将指定参赛者的成绩清零(换句话说,将其从排行榜中删除)。题目保证在调用此函数前,该参赛者已有成绩,并且在榜单上。
请注意,在初始状态下,排行榜是空的。

链接:https://leetcode.cn/problems/design-a-leaderboard

class Leaderboard:def __init__(self):self.board = dict()def addScore(self, playerId: int, score: int) -> None:if playerId not in self.board:self.board[playerId] = scoreelse:self.board[playerId] += scoredef top(self, K: int) -> int:a = sorted(self.board.items(), key=lambda x:x[1], reverse=True)ans = 0a = a[:K]for k, v in a:ans += vreturn ansdef reset(self, playerId: int) -> None:if playerId in self.board:del self.board[playerId]# Your Leaderboard object will be instantiated and called as such:
# obj = Leaderboard()
# obj.addScore(playerId,score)
# param_2 = obj.top(K)
# obj.reset(playerId)

1265、逆序打印不可变链表

给您一个不可变的链表,使用下列接口逆序打印每个节点的值:

ImmutableListNode: 描述不可变链表的接口,链表的头节点已给出。
您需要使用以下函数来访问此链表(您 不能 直接访问 ImmutableListNode):

ImmutableListNode.printValue():打印当前节点的值。
ImmutableListNode.getNext():返回下一个节点。
输入只用来内部初始化链表。您不可以通过修改链表解决问题。也就是说,您只能通过上述 API 来操作链表。

链接:https://leetcode.cn/problems/print-immutable-linked-list-in-reverse

# """
# This is the ImmutableListNode's API interface.
# You should not implement it, or speculate about its implementation.
# """
# class ImmutableListNode:
#     def printValue(self) -> None: # print the value of this node.
#     def getNext(self) -> 'ImmutableListNode': # return the next node.class Solution:def printLinkedListInReverse(self, head: 'ImmutableListNode') -> None:def dfs(node):if node == None: returndfs(node.getNext())node.printValue()dfs(head)

1215、进步数

如果一个整数上的每一位数字与其相邻位上的数字的绝对差都是 1,那么这个数就是一个「步进数」。

例如,321 是一个步进数,而 421 不是。

给你两个整数,low 和 high,请你找出在 [low, high] 范围内的所有步进数,并返回 排序后 的结果。

链接:https://leetcode.cn/problems/stepping-numbers

BFS

class Solution:def countSteppingNumbers(self, low: int, high: int) -> List[int]:res = []if low == 0:res.append(low)queue = [x for x in range(1,10)]while queue:tmp = queue.pop(0)if tmp > high:return resif tmp >= low:res.append(tmp)last = tmp % 10if last > 0:queue.append(tmp*10 + last - 1)if last < 9:queue.append(tmp*10 + last + 1)return res

1256、加密数字

给你一个非负整数 num ,返回它的「加密字符串」。

加密的过程是把一个整数用某个未知函数进行转化,你需要从下表推测出该转化函数:

class Solution:def encode(self, num: int) -> str:new_num = bin(num+1)print(new_num)length = len(str(new_num))return str(new_num)[3: length]

1182、与目标颜色间的最短距离

给你一个数组 colors,里面有 1、2、 3 三种颜色。

我们需要在 colors 上进行一些查询操作 queries,其中每个待查项都由两个整数 i 和 c 组成。
现在请你帮忙设计一个算法,查找从索引 i 到具有目标颜色 c 的元素之间的最短距离。
如果不存在解决方案,请返回 -1。

链接:https://leetcode.cn/problems/shortest-distance-to-target-color

class Solution:def shortestDistanceColor(self, colors: List[int], queries: List[List[int]]) -> List[int]:ans = []dic_color = defaultdict(list)for idx,x in enumerate(colors):dic_color[x].append(idx)for x,y in queries:if y not in dic_color:ans.append(-1)else:if colors[x] == y:ans.append(0)else:arr = dic_color[y]left, right = 0, len(arr)-1if x<=arr[left]:ans.append(abs(arr[left]-x))elif x>=arr[right]:ans.append(abs(arr[right]-x))else:while left <= right:mid = (left+right)//2if x > arr[mid]: left = mid+1else: right = mid-1ans.append(min(abs(arr[left] - x), abs(arr[left - 1] - x)))return ans

1230、抛掷硬币

有一些不规则的硬币。在这些硬币中,prob[i] 表示第 i 枚硬币正面朝上的概率。

请对每一枚硬币抛掷 一次,然后返回正面朝上的硬币数等于 target 的概率。

链接:https://leetcode.cn/problems/toss-strange-coins

class Solution:def probabilityOfHeads(self, prob: List[float], target: int) -> float:m = len(prob)dp = [[0 for _ in range(target+1)] for _ in range(m+1)]dp[0][0] = 1for i in range(m):dp[i+1][0] = dp[i][0]*(1-prob[i])for i in range(1,m+1):for j in range(1,target+1):dp[i][j] = dp[i-1][j]*(1-prob[i-1])+dp[i-1][j-1]*prob[i-1]return dp[-1][-1]

1258、近义词替换

给你一个近义词表 synonyms 和一个句子 text , synonyms 表中是一些近义词对 ,你可以将句子 text 中每个单词用它的近义词来替换。

请你找出所有用近义词替换后的句子,按 字典序排序 后返回。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/synonymous-sentences

PS:利用并查集,确定近义词集合

class Union:def __init__(self, n):self.father = [x for x in range(n)]def findFather(self, x):while x!=self.father[x]:self.father[x] = self.father[self.father[x]]x = self.father[x]return xdef union(self,x,y):root1 = self.findFather(x)root2 = self.findFather(y)if root1 != root2:if root2 > root1:self.father[root2] = root1else:self.father[root1] = root2def isConnect(self,x,y):return self.findFather(x)==self.findFather(y)class Solution:def generateSentences(self, synonyms: List[List[str]], text: str) -> List[str]:arr_str = text.split(' ')word_id_dict = defaultdict(int)idx = 0for x,y in synonyms:if x not in word_id_dict:word_id_dict[x] = idxidx+=1if y not in word_id_dict:word_id_dict[y] = idxidx+=1uf = Union(idx)for x, y in synonyms:uf.union(word_id_dict[x], word_id_dict[y])syn_dict = defaultdict(set)for x in word_id_dict.keys():for y in word_id_dict.keys():if x==y:continueif uf.isConnect(word_id_dict[x], word_id_dict[y]):syn_dict[x].add(y)self.res = set()self.res.add(text)def dfs(arr, i):if i == len(arr):returnfor j in range(i,len(arr)):print(arr[j])if arr[j] in syn_dict:for v in syn_dict[arr[j]]:tmp = arr.copy()tmp[j] = vself.res.add(' '.join(tmp))dfs(tmp, j+1)tmp = arr.copy()self.res.add(' '.join(tmp))dfs(tmp, j+1)dfs(arr_str,0)self.res = list(self.res)self.res.sort()return self.res

1236、网络爬虫

给定一个链接 startUrl 和一个接口 HtmlParser ,请你实现一个网络爬虫,以实现爬取同 startUrl 拥有相同 域名标签 的全部链接。该爬虫得到的全部链接可以 任何顺序 返回结果。

链接:https://leetcode.cn/problems/web-crawler

# """
# This is HtmlParser's API interface.
# You should not implement it, or speculate about its implementation
# """
#class HtmlParser(object):
#    def getUrls(self, url):
#        """
#        :type url: str
#        :rtype List[str]
#        """class Solution:def crawl(self, startUrl: str, htmlParser: 'HtmlParser') -> List[str]:start_strr=startUrl[7:]start_name = 'http://'+start_strr.split('/')[0]res = set()res.add(startUrl)st = [startUrl]while st:tmp_str = st.pop(0)res.add(tmp_str)for x in htmlParser.getUrls(tmp_str):if x not in res and x.startswith(start_name):st.append(x)return (res)

1257、最小化公共区域

给你一些区域列表 regions ,每个列表的第一个区域都包含这个列表内所有其他区域。

很自然地,如果区域 X 包含区域 Y ,那么区域 X 比区域 Y 大。
给定两个区域 region1 和 region2 ,找到同时包含这两个区域的 最小 区域。
如果区域列表中 r1 包含 r2 和 r3 ,那么数据保证 r2 不会包含 r3 。
数据同样保证最小公共区域一定存在。

链接:https://leetcode.cn/problems/smallest-common-region

class Solution:def findSmallestRegion(self, regions: List[List[str]], region1: str, region2: str) -> str:fa_dict = dict()for region in regions:fa = region[0]for child in region[1:]:fa_dict[child] = far1, r2 = region1, region2r1_fas = [r1]while r1 in fa_dict:r1 = fa_dict[r1]r1_fas.append(r1)while r2 in fa_dict:if r2 in r1_fas:return r2r2 = fa_dict[r2]return r2

1272、删除区间

实数集合可以表示为若干不相交区间的并集,其中每个区间的形式为 [a, b)(左闭右开),表示满足 a <= x < b 的所有实数 x 的集合。如果某个区间 [a, b) 中包含实数 x ,则称实数 x 在集合中。

给你一个 有序的 不相交区间列表 intervals 。intervals 表示一个实数集合,其中每一项 intervals[i] = [ai, bi] 都表示一个区间 [ai, bi) 。再给你一个要删除的区间 toBeRemoved 。

返回 一组实数,该实数表示intervals 中 删除 了 toBeRemoved 的部分 。换句话说,返回实数集合,并满足集合中的每个实数 x 都在 intervals 中,但不在 toBeRemoved 中。你的答案应该是一个如上所述的 有序的 不相连的间隔列表 。

链接:https://leetcode.cn/problems/remove-interval

class Solution:def removeInterval(self, intervals: List[List[int]], toBeRemoved: List[int]) -> List[List[int]]:res = []for x,y in intervals:tmp_x = min(x, toBeRemoved[0])tmp_y = max(y, toBeRemoved[1])if tmp_x == x and tmp_y == y:if tmp_x == x == toBeRemoved[0] and tmp_y == y == toBeRemoved[1]:continueelif tmp_x == x == toBeRemoved[0]:res.append([toBeRemoved[1], y])elif tmp_y == y == toBeRemoved[1]:res.append([x, toBeRemoved[0]])else:res.append([x,toBeRemoved[0]])res.append([toBeRemoved[1],y])elif tmp_x == x and tmp_y == toBeRemoved[1]:res.append([x, min(y,toBeRemoved[0])])elif tmp_x == toBeRemoved[0] and tmp_y == y:res.append([max(x,toBeRemoved[1]), y])return res

1273、删除树节点

class Solution:def deleteTreeNodes(self, nodes: int, parent: List[int], value: List[int]) -> int:edges = [[] for _ in range(nodes)]for x, p in enumerate(parent):if p != -1:edges[p].append(x)cnt_node = [1 for _ in range(nodes)]def dfs(node):for v in edges[node]:dfs(v)value[node] += value[v]cnt_node[node] += cnt_node[v]if value[node] == 0:cnt_node[node] = 0dfs(0)return cnt_node[0]

758、字符串加粗单词

class Solution:def boldWords(self, words: List[str], s: str) -> str:n = len(s)mask = [False for _ in range(n)]for i in range(n):for word in words:if i+len(word)<=n and s[i:i+len(word)]==word:for j in range(len(word)):mask[i+j] = Trueres = ''for idx, x in enumerate(mask):if mask[idx] and (idx==0 or mask[idx-1]==False):res+='<b>'res+=s[idx]if mask[idx] and (idx==n-1 or mask[idx+1]==False):res+='</b>'return res

1062、最长重复子串

二分查找 binary-search

class Solution:def boldWords(self, words: List[str], s: str) -> str:n = len(s)mask = [False for _ in range(n)]for i in range(n):for word in words:if i+len(word)<=n and s[i:i+len(word)]==word:for j in range(len(word)):mask[i+j] = Trueres = ''for idx, x in enumerate(mask):if mask[idx] and (idx==0 or mask[idx-1]==False):res+='<b>'res+=s[idx]if mask[idx] and (idx==n-1 or mask[idx+1]==False):res+='</b>'return res

LCP 12. 小张刷题计划

class Solution:def minTime(self, time: List[int], m: int) -> int:left, right = 0, sum(time)while left<right:L = (left+right)//2if self.isTime(L, time, m):right = Lelse:left = L+1return leftdef isTime(self, Limit, time, m):cur_time = 0max_time = time[0]days = 1for x in time[1:]:if cur_time + min(max_time, x)<=Limit:cur_time += min(max_time,x)max_time = max(max_time, x)else:cur_time = 0days += 1# max_time = min(max_time, x)max_time = xif days>m:return Falseelse:return True

625、最小因式分解

给定一个正整数 a,找出最小的正整数 b 使得 b 的所有数位相乘恰好等于 a。

如果不存在这样的结果或者结果不是 32 位有符号整数,返回 0。

class Solution:def smallestFactorization(self, num: int) -> int:res = 0weight = 1if num<=9:return numfor x in range(9,1,-1):while num%x == 0:num //= xres = weight*x + resweight *= 10if res >= 2**31-1:return 0if num!=1:return 0return res

750、角矩形的数量

动态规划
给定一个只包含 0 和 1 的 m x n 整数矩阵 grid ,返回 其中 「角矩形 」的数量 。

一个「角矩形」是由四个不同的在矩阵上的 1 形成的 轴对齐 的矩形。注意只有角的位置才需要为 1。
注意:4 个 1 的位置需要是不同的。

链接:https://leetcode.cn/problems/number-of-corner-rectangles

class Solution:def countCornerRectangles(self, grid: List[List[int]]) -> int:m, n = len(grid), len(grid[0])dp = [[0 for _ in range(n)] for _ in range(n)]res = 0for i in range(m):for j in range(n):if grid[i][j]==1:for k in range(j+1,n):if grid[i][k]==1:res+=dp[j][k]dp[j][k]+=1return res

三、困难

305、岛屿数量二

并查集的应用
给你一个大小为 m x n 的二进制网格 grid 。网格表示一个地图,其中,0 表示水,1 表示陆地。最初,grid 中的所有单元格都是水单元格(即,所有单元格都是 0)。

可以通过执行 addLand 操作,将某个位置的水转换成陆地。给你一个数组 positions ,其中 positions[i] = [ri, ci] 是要执行第 i 次操作的位置 (ri, ci) 。

返回一个整数数组 answer ,其中 answer[i] 是将单元格 (ri, ci) 转换为陆地后,地图中岛屿的数量。

岛屿 的定义是被「水」包围的「陆地」,通过水平方向或者垂直方向上相邻的陆地连接而成。你可以假设地图网格的四边均被无边无际的「水」所包围。

链接:https://leetcode.cn/problems/number-of-islands-ii

class FindUnion:def __init__(self,n):self.father = [x for x in range(n)]self.cluster = 0self.size = [1 for _ in range(n)]def findFather(self,x):while x!=self.father[x]:self.father[x] = self.father[self.father[x]]x = self.father[x]return xdef Union(self,x,y):root_x = self.findFather(x)root_y = self.findFather(y)if root_x == root_y:return Trueelse:if root_x > root_y:self.father[root_x] = root_yself.size[root_x] += self.size[root_y]else:self.father[root_y] = root_xself.size[root_y] += self.size[root_x]self.cluster -= 1return Trueclass Solution:def numIslands2(self, m: int, n: int, positions: List[List[int]]) -> List[int]:uf = FindUnion(m*n)seen = set()res = []for x,y in positions:ID = x*n+yif ID in seen:res.append(uf.cluster)continueseen.add(ID)uf.cluster += 1for nr, nc in [(x+1,y),(x-1,y),(x,y+1),(x,y-1)]:if 0<=nr<m and 0<=nc<n:Id2 = nr*n+ncif Id2 in seen:uf.Union(ID, Id2)res.append(uf.cluster)return res

124、二叉树中的最大路径和

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

链接:https://leetcode.cn/problems/binary-tree-maximum-path-sum

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def maxPathSum(self, root: Optional[TreeNode]) -> int:self.res = -float('inf')def dfs(root):if not root: return 0left = dfs(root.left)right = dfs(root.right)self.res=max(self.res,root.val+left+right, root.val+left, root.val+right, root.val)print(root.val, self.res)return max(root.val+left, root.val+right, root.val)dfs(root)return self.res

72、编辑距离

动态规划
给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符

链接:https://leetcode.cn/problems/edit-distance

class Solution:def minDistance(self, word1: str, word2: str) -> int:m, n = len(word1), len(word2)dp = [[0 for _ in range(n+1)]for _ in range(m+1)]for i in range(m+1):dp[i][0] = ifor i in range(n+1):dp[0][i] = ifor i in range(1,m+1):for j in range(1,n+1):left = dp[i][j-1] + 1right = dp[i-1][j] + 1lr = dp[i-1][j-1]if word1[i-1]!=word2[j-1]:lr += 1dp[i][j] = min(left, right, lr)return dp[m][n]

912、排序数组

快排

class Solution:def sortArray(self, nums: List[int]) -> List[int]:def getIndex(nums, left, right):p = nums[left]while left < right:while left < right and p<=nums[right]:right -= 1nums[left] = nums[right]while left < right and p>=nums[left]:left += 1nums[right] = nums[left]nums[left] = preturn leftdef randomIndex(nums, left, right):index = random.randint(left, right)nums[left], nums[index] = nums[index],nums[left]return getIndex(nums,left,right)def quickSort(nums, left, right):if left<right:mid = randomIndex(nums,left,right)quickSort(nums, left, mid-1)quickSort(nums, mid+1, right)quickSort(nums,0,len(nums)-1)return nums

【Leetcode】精选算法top200道(二)相关推荐

  1. LeetCode精选算法100题,从入门到入赘

    文章目录 前言 1.两数之和 2.两数相加 3.无重复字符的最长子串 4.寻找两个正序数组的中位数 5.最长回文子串 6. Z字形变换 7.整数反转 8.字符串转换整数 (atoi) 9.正则表达式匹 ...

  2. 八十二、Python | Leetcode贪心算法系列

    @Author:Runsen @Date:2020/7/5 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

  3. python leetcode_八十二、Python | Leetcode贪心算法系列

    @Author:Runsen @Date:2020/7/5 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

  4. 刷题汇总(三)leetcode 精选50题 C++答案总结

    题目来源 腾讯精选练习(50 题) 相关: 刷题汇总(一)leetcode 精选50题 JavaScript答案总结 刷题汇总(二)剑指Offer 66题 C++答案总结 刷题汇总(四)技术类编程题汇 ...

  5. 代码随想录1刷—贪心算法篇(二)

    代码随想录1刷-贪心算法篇(二) [452. 用最少数量的箭引爆气球](https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-b ...

  6. 算法之道:形而之上谓之道

    1966年3月的一天,美国加州大学洛杉矶分校的Andrew J. Viterbi教授在给研究生讲解缠绕编码的时序译码算法SDCD.但不管他如何讲解,学生就是听不明白.思来想去,Viterbi觉得学生不 ...

  7. 《算法之道》精华 经典算法部分

    <算法之道>精华 经典算法部分 本书作者邹恒明,作者另有一本书<数据结构之弦>,以及<操作系统之哲学原理>都是非常好的书 这本书能够算得上是深入浅出,文笔非常好.作 ...

  8. 观、砺、破——我的算法之道

    观.砺.破--我的算法之道 数学乃至算法仅仅是很多人生命中的过客,是可望而不可及的遥远存在.但是,当下这个"数据教横行","AI满天飞"的社会在不断地拉近人们与 ...

  9. 结构之法算法之道CSDN博客-第一期全部博文集锦[CHM 文件下载]

    结构之法算法之道CSDN博客- 博文集锦第一期CHM 文件 首先恭喜你,你得到了一份非常宝贵的资源. 此份文件是截止到2011年2月27日,本博客.结构之法算法之道博客内的第一期全部内容的集锦,同时, ...

最新文章

  1. DOCTYPE声明作用及用法详解
  2. python的模块、包、库区别。导入包/模块的方式
  3. JVM学习(2)——技术文章里常说的堆,栈,堆栈到底是什么,从os的角度总结
  4. boost::hana::min用法的测试程序
  5. 在对比了 GitHub 5000 个 Python 项目之后,我们精选出了这 36 个!
  6. test 7 3-22 2021省选模拟赛seven
  7. python函数封装计算n运算_在Python里面怎么可以运算出999999999**999999999,求思路?...
  8. winform最小化后隐藏到右下角,单击或双击后恢复
  9. 判断闰年的c语言程序_身为程序员还记得C语言经典算法(附带答案)吗?
  10. python数据分析:Matplotlib
  11. js实现双人对战五子棋
  12. java对接短信接口
  13. CV LRO mission (LROC introduction)
  14. 扇入Fan-in和扇出Fan-out
  15. C++学习方法(经典)
  16. 计算机蓝屏代码0xc0000020,Win10系统运行程序提示“损坏的映像 错误0xc0000020”怎么解决...
  17. Android NFC开发详解 总结和NFC读卡实例解析
  18. Macbook百度网盘不限速下载
  19. Android大作业跑酷游戏《Android studio》
  20. 永大电梯服务器显示连接断开,提供上海永大电梯服务器

热门文章

  1. java支持scss_Java的SASS实现?
  2. calc.relimp学习笔记(R语言)
  3. Android架构分析之硬件抽象层(HAL)
  4. 前女友闺蜜给我发了一个压缩包,居然还带密码?暴力破解ZIP加密文件的密码!
  5. 如何使用ARM协处理器CP15在32位ARRCH模式下操作64位寄存器)
  6. 让你久等了!《开源安全运维平台OSSIM疑难解析--入门篇》9月上市
  7. 极速办公(excel)如何快速计算排名
  8. 当命运欺骗了你,落到谷底时,唯一的出口就是向上
  9. MFC软件常见问题解决
  10. adb shell打开开发者选项