至少有K个重复字符的最长子串
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
示例 1:
输入:
s = “aaabb”, k = 3
输出:
3
最长子串为 “aaa” ,其中 ‘a’ 重复了 3 次。
示例 2:
输入:
s = “ababbc”, k = 2
输出:
5
最长子串为 “ababb” ,其中 ‘a’ 重复了 2 次, ‘b’ 重复了 3 次。
解法
看题目有点像用动态规划的方法来做,但是并没有好方法,而是用递归。
首先判断字符串的长度,若小于k,直接返回0。然后对字符串中的每一个字符依次判断其出现次数,若次数小于k,则在不包括该字符的子串中继续递归判断,最后返回各个符合条件子串长度的最大值即可。
代码非常的Python化
class Solution(object):
def longestSubstring(self, s, k):
"""
:type s: str
:type k: int
:rtype: int
"""
if len(s) < k:
return 0
for x in set(s):
if s.count(x) < k:
return max(self.longestSubstring(sub, k) for sub in s.split(x))
return len(s)
爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
class Solution(object):
def climbStairs(self, n, dic={
}):
"""
:type n: int
:rtype: int
"""
if n in dic:
return dic[n]
if n in [0, 1, 2, 3]:
return n
res = self.climbStairs(n - 1, dic) + self.climbStairs(n - 2, dic)
dic[n] = res
return res
第K个语法符号
在第一行我们写上一个 0。接下来的每一行,将前一行中的0替换为01,1替换为10。
给定行数 N 和序数 K,返回第 N 行中第 K个字符。(K从1开始)
例子:
输入: N = 1, K = 1
输出: 0
输入: N = 2, K = 1
输出: 0
输入: N = 2, K = 2
输出: 1
输入: N = 4, K = 5
输出: 1
解释:
第一行: 0
第二行: 01
第三行: 0110
第四行: 01101001
注意:
N 的范围 [1, 30].
K 的范围 [1, 2^(N-1)].
解法
递归法:第N行的K位是根据第N-1行的M位得到的。
M = (K + 1)/2,然而再判断是0还是1即可
class Solution(object):
def kthGrammar(self, N, K):
"""
:type N: int
:type K: int
:rtype: int
"""
if N == 1:
return 0
if K == 0:
return 0
if K % 2 == 0:
x = K // 2
y = 1
else:
x = K // 2 + 1
y = 0
last = self.kthGrammar(N - 1, x)
if last == 0:
z = [0, 1]
else:
z = [1, 0]
return z[y]
从二维矩阵中查找是否存在某个字符串s
# 二维数组,随机字母,给定字符串,判断是否在二维数组中。
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
def dfs(nums, s, i, j, k):
if i < 0 or j < 0 or i >= len(nums) or j >= len(nums[0]):
return False
if nums[i][j] == s[k]:
tmp = nums[i][j]
nums[i][j] = '*'
if k == len(s) - 1:
return True
else:
for m in range(4):
x, y = i + dx[m], j + dy[m]
if dfs(nums, s, x, y, k + 1):
return True
nums[i][j] = tmp
return False
def find(nums, s):
for i in range(len(nums)):
for j in range(len(nums[0])):
if dfs(nums, s, i, j, 0):
return True
return False
机器人的运动范围
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
解法
- BFS:
- DFS:注意对范围的判断
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.res = 0
self.vis = []
self.dx = [-1, 0, 1, 0]
self.dy = [0, -1, 0, 1]
def get_num(self, num):
cnt = 0
while num > 0:
cnt += num % 10
num /= 10
return cnt
def movingCount(self, threshold, rows, cols, x = 0, y = 0):
# write code here
if threshold <= 0:
return 0
if x < 0 or x >= rows or y < 0 or y >= cols or (x, y) in self.vis:
return
if self.get_num(x) + self.get_num(y) > threshold:
return
self.res += 1
self.vis.append((x, y))
for i in range(4):
self.movingCount(threshold, rows, cols, x + self.dx[i], y + self.dy[i])
return self.res
子树中标签相同的节点数
给你一棵树(即,一个连通的无环无向图),这棵树由编号从 0 到 n - 1 的 n 个节点组成,且恰好有 n - 1 条 edges 。树的根节点为节点 0 ,树上的每一个节点都有一个标签,也就是字符串 labels 中的一个小写字符(编号为 i 的 节点的标签就是 labels[i] )
边数组 edges 以 edges[i] = [ai, bi] 的形式给出,该格式表示节点 ai 和 bi 之间存在一条边。
返回一个大小为 n 的数组,其中 ans[i] 表示第 i 个节点的子树中与节点 i 标签相同的节点数。
树 T 中的子树是由 T 中的某个节点及其所有后代节点组成的树。
输入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], labels = “abaedcd”
输出:[2,1,1,1,1,1,1]
解释:节点 0 的标签为 ‘a’ ,以 ‘a’ 为根节点的子树中,节点 2 的标签也是 ‘a’ ,因此答案为 2 。注意树中的每个节点都是这棵子树的一部分。
节点 1 的标签为 ‘b’ ,节点 1 的子树包含节点 1、4 和 5,但是节点 4、5 的标签与节点 1 不同,故而答案为 1(即,该节点本身)。
提示:
1 <= n <= 10^5
edges.length == n - 1
edges[i].length == 2
0 <= ai, bi < n
ai != bi
labels.length == n
labels 仅由小写英文字母组成
解法
用dfs递归的记录每个节点子树上的标签都有多少个,然后返回的时候加起来就可以了。
class Solution:
def countSubTrees(self, n: int, edges: List[List[int]], labels: str) -> List[int]:
dic = {
}
for s, e in edges:
if s not in dic:
dic[s] = []
if e not in dic:
dic[e] = []
dic[s].append(e)
dic[e].append(s)
res = [0] * n
vis = set()
def dfs(idx):
vis.add(idx)
char_dic = {
}
char_dic[labels[idx]] = 1
for node in dic[idx]:
if node not in vis:
ne_dic = dfs(node)
for c in ne_dic:
if c not in char_dic:
char_dic[c] = 0
char_dic[c] += ne_dic[c]
res[idx] = char_dic[labels[idx]]
return char_dic
dfs(0)
return res
排列组合问题:
参考:https://juejin.im/post/5e5fc7eae51d4526c26fc732
回溯法的模式概括:
res = []
tmp = []
if <1.设置条件:把需要的当前列表加入res>:
res.append(当前列表)
return res
for 选择 in 选择列表:
<2.做选择>
<3.递归调用> backtrack(选择列表,当前列表,res)
<4.撤销选择>
全排列:
给定一个没有重复数字的序列,返回其所有可能的全排列。 示例: Input: [1,3,5] Output: [1,3,5], [1,5,3], [3,1,5], [3,5,1], [5,1,3], [5,3,1]
def permute(self, nums: List[int]) -> List[List[int]]:
# 函数输入为空时的特殊情况
if not nums: return nums
# 参数赋值初始化
res = []
tmp = []
# 调用backtrack函数,在类(class Solution)中要用self调用函数
self.<