目录
1-拼写单词-easy。哈希表、字符串
给你一份『词汇表』(字符串数组) words
和一张『字母表』(字符串) chars
。
假如你可以用 chars
中的『字母』(字符)拼写出 words
中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
注意:每次拼写时,chars
中的每个字母都只能用一次。
返回词汇表 words
中你掌握的所有单词的 长度之和。
示例 1:
输入:words = ["cat","bt","hat","tree"], chars = "atach"
输出:6
解释:
可以形成字符串 "cat" 和 "hat",所以答案是 3 + 3 = 6。
示例 2:
输入:words = ["hello","world","leetcode"], chars = "welldonehoneyr"
输出:10
解释:
可以形成字符串 "hello" 和 "world",所以答案是 5 + 5 = 10。
DIY的想法就是对words中的每个词都看看能不能用chars组成,但这样每次都要新建一个新chars的字典,后来看大神们的做法也差不多,难道考点利用题目条件说只有小写字母所以用26长度的数组代替字典?
也有对每个词新建字典然后比较chars里的频数的方法,本质是一样的
class Solution:
def countCharacters(self, words: List[str], chars: str) -> int:
if not words or not chars:
return 0
dic = [0]*26
res = 0
for w in chars:
dic[ord(w)-ord('a')] += 1
for w in words:
cur = dic[:]
flag = True
for c in w:
if cur[ord(c)-ord('a')] <= 0:
flag = False
break
cur[ord(c)-ord('a')] -= 1
if flag:
res += len(w)
return res
2-最大层内元素和-medium。树、层序遍历
给你一个二叉树的根节点 root
。设根节点位于二叉树的第 1
层,而根节点的子节点位于第 2
层,依此类推。
请你找出层内元素之和 最大 的那几层(可能只有一层)的层号,并返回其中 最小 的那个。
示例:
输入:[1,7,0,7,-8,null,null]
输出:2
解释:
第 1 层各元素之和为 1,
第 2 层各元素之和为 7 + 0 = 7,
第 3 层各元素之和为 7 + -8 = -1,
所以我们返回第 2 层的层号,它的层内元素之和最大。
没什么难点,理解清楚题意就是如果最大的和有多组,返回层数最小的那一层。考察层序遍历,涉及到队列机制
还有好久没用DFS方法
# BFS
class Solution:
def maxLevelSum(self, root: TreeNode) -> int:
if not root:
return 0
res = root.val
level = 1
q = [root]
i = 0
while q:
cur_res = 0
for _ in range(len(q)):
cur = q.pop(0)
cur_res += cur.val
if cur.left:
q.append(cur.left)
if cur.right:
q.append(cur.right)
i += 1
if cur_res > res:
res = cur_res
level = i
return level
# DFS
class Solution:
def maxLevelSum(self, root: TreeNode) -> int:
if not root:
return 0
res = {}
self.dfs(root, res, 1)
ans = 0
ssum = float('-inf')
for k in res:
if res[k] > ssum:
ssum = res[k]
ans = k
return ans
def dfs(self, root, res, level):
if not root:
return
res[level] = res.get(level, 0) + root.val
self.dfs(root.left, res, level+1)
self.dfs(root.right, res, level+1)
return
3-地图分析-medium。BFS
你现在手里有一份大小为 N x N 的『地图』(网格) grid
,上面的每个『区域』(单元格)都用 0
和 1
标记好了。其中 0
代表海洋,1
代表陆地,你知道距离陆地区域最远的海洋区域是是哪一个吗?请返回该海洋区域到离它最近的陆地区域的距离。
我们这里说的距离是『曼哈顿距离』( Manhattan Distance):(x0, y0)
和 (x1, y1)
这两个区域之间的距离是 |x0 - x1| + |y0 - y1|
。
如果我们的地图上只有陆地或者海洋,请返回 -1
。
示例 1:
输入:[[1,0,1],[0,0,0],[1,0,1]]
输出:2
解释:
海洋区域 (1, 1) 和所有陆地区域之间的距离都达到最大,最大距离为 2。
示例 2:
输入:[[1,0,0],[0,0,0],[0,0,0]]
输出:4
解释:
海洋区域 (2, 2) 和所有陆地区域之间的距离都达到最大,最大距离为 4。
DIY的想法是每个0位置都BFS找距离最短的1,最后比较出最大的,但超时,确实是有很多重复计算。所以这道题的正确解法应该是从每个1位置出发去标记周围的cell,因为是BFS,所以对于一个water cell来说肯定是距离它最近的land cell最先把它标记,其他要么和它等距要么更远。跟这道题相近的有大西洋和太平洋水流向的那题,计算水流向的同时把距离也更新了
逆向思维,或者说以后这种题就都用这种套路把
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
if not grid:
return -1
m = len(grid)
n = len(grid[0])
res = -1
dp = [[-1 for _ in range(n)] for _ in range(m)]
around = [[-1, 0], [1, 0], [0, -1], [0, 1]]
q = []
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
dp[i][j] = 0
q.append((i, j))
self.helper(grid, m, n, q, dp, around)
for i in range(m):
for j in range(n):
res = max(res, dp[i][j])
return res if res != 0 else -1
def helper(self, grid, m, n, q, dp, around):
while q:
x, y = q.pop(0)
for d in around:
n_x = x + d[0]
n_y = y + d[1]
if n_x < 0 or n_x >= m or n_y < 0 or n_y >= n or dp[n_x][n_y] != -1:
continue
dp[n_x][n_y] = dp[x][y]+1
q.append((n_x, n_y))
return
4-按字典序排在最后的子串-hard。栈、字典序
给你一个字符串 s
,找出它的所有子串并按字典序排列,返回排在最后的那个子串。
示例 1:
输入:"abab"
输出:"bab"
解释:我们可以找出 7 个子串 ["a", "ab", "aba", "abab", "b", "ba", "bab"]。按字典序排在最后的子串是 "bab"。
示例 2:
输入:"leetcode"
输出:"tcode"
2种方法
- 暴力+剪枝,暴力就是找到所有子串,剪枝就是字典序最大的子串必然是包含最后一个字符的又是连续的,所以必然是从某个位置开始slice到最后构成的子串,python的强大max还能比较字符串的字典序,所以这道题可以这么暴力或者说带点作弊的思想解把
- 当成hard算法题来解的话,这道题必然要用到单调栈,但只能作为解题的第一步,
# 剪枝后的暴力
class Solution:
def lastSubstring(self, s: str) -> str:
res = ''
for i in range(len(s)):
res = max(res, s[i:])
return res
# 正解