一、力扣
1、子结构判断
class Solution {
TreeNode B;
boolean res;
public boolean isSubStructure(TreeNode A, TreeNode B) {
// 空树不能作为子结构
if (B == null) return false;
// 初始化目标子结构
this.B = B;
// 重置结果标记
this.res = false;
// 从根节点开始深度优先遍历主树
dfs(A);
return res;
}
public void dfs(TreeNode A) {
if (A == null) return;
// 发现值匹配的节点,进行结构校验
if (A.val == B.val && check(A, B)) {
res = true; // 找到匹配,设置结果
}
// 递归遍历左右子树(即使已找到结果,仍需遍历完整棵树)
dfs(A.left);
dfs(A.right);
}
public boolean check(TreeNode fir, TreeNode sec) {
// 子结构遍历完成,结构匹配
if (sec == null) return true;
// 主树已遍历完但子结构未完成,结构不匹配
if (fir == null) return false;
// 节点值不匹配
if (fir.val != sec.val) return false;
// 递归校验左右子树
return check(fir.left, sec.left) && check(fir.right, sec.right);
}
}
2、! 字典序的第K小数字
class Solution {
public int findKthNumber(int n, int k) {
//从根节点下面的第一个结点1开始遍历,由于数据范围很大,所以用long
long cur = 1;
//从1出发开始往后按字典序从小到大的顺序走k-1步到达的就是 字典序的第K小数字
k -= 1;
while (k > 0) {
//得到以当前结点为根的所有子树节点数目
int nodes = getNodes(n, cur);
//如果k要大于当前根节点下所有子树结点的数目,就向右侧节点走(->2->3->4->5->6->7->8->9):字典序上升nodes位
if (k >= nodes) {
//减去已经遍历的个数
k -= nodes;
//根节点右移
cur ++;
}
//如果k小于当前根节点下所有子树结点的数目,说明答案就在当前根节点的子树结点中
else {
//减去根节点的数量1
k -= 1;
//将根结点移动到下一层(每一层右10个结点)
cur *= 10;
}
}
//最终k = 0时,就找到了答案
return (int)cur;
}
// 计算以cur为根的子树节点数目,所有节点的值必须 <= n
private int getNodes(int n, long cur){
// 记录子树中的全部节点数目
long totalNodes = 0;
// 当前节点右侧右边节点的值,用于计算一行有几个元素
long next = cur + 1;
while(cur <= n){
//取整行结点的个数,可能全部都满了,也可能是叶子结点,没有充满
totalNodes += Math.min(n - cur + 1, next - cur);
//cur - cur在当前层的第一个结点, next - cur右侧根结点的第一个结点
next *= 10;
cur *= 10;
}
return (int)totalNodes;
}
}
3、不同的子序列
class Solution {
public int numDistinct(String s, String t) {
int m = s.length(), n = t.length();
int[][] dp = new int[m + 1][n + 1];//dp[i][j] 为以i为结尾s子序列的出现j结尾子序列个数
for (int i = 0; i < m + 1; i++) {
dp[i][0] = 1;
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (s.charAt(i) == t.charAt(j)) {
dp[i + 1][j + 1] = dp[i][j] + dp[i][j + 1];
} else {
dp[i + 1][j + 1] = dp[i][j + 1];
}
}
}
return dp[m][n];
}
}
4、两个字符串的删除操作
dp[i][j]为使word1[:i]和word2[:j]相同的最小步数。
class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length(), n = word2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i <= m; i++) {
dp[i][0] = i;
}
for (int i = 0; i <= n; i++) {
dp[0][i] = i;
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (word1.charAt(i) == word2.charAt(j)) {
dp[i + 1][j + 1] = dp[i][j];
} else {
dp[i + 1][j + 1] = Math.min(dp[i][j + 1], dp[i + 1][j]) + 1;
}
}
}
return dp[m][n];
}
}
5、编辑距离
class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length(), n = word2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i < m + 1; i++) {
dp[i][0] = i;
}
for (int i = 0; i < n + 1; i++) {
dp[0][i] = i;
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (word1.charAt(i) == word2.charAt(j)) {
dp[i + 1][j + 1] = dp[i][j];
} else {
dp[i + 1][j + 1] = Math.min(dp[i][j + 1], Math.min(dp[i + 1][j], dp[i][j])) + 1;
}
}
}
return dp[m][n];
}
}
6、回文子串
class Solution {
public int countSubstrings(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
int res = 0;
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
if (s.charAt(i) == s.charAt(j)) {
if (j - i <= 1) {
res++;
dp[i][j] = true;
} else if (dp[i + 1][j - 1]) {
dp[i][j] = true;
res++;
}
}
}
}
return res;
}
}
7、最长回文子序列
class Solution {
public int longestPalindromeSubseq(String s) {
int n = s.length();
int[][] dp = new int[n][n];
for (int i = 0; i < n; i++) {
dp[i][i] = 1;
}
for (int j = 1; j < n; j++) {
for (int i = j - 1; i >= 0; i--) {
if (s.charAt(i) == s.charAt(j)) {
dp[i][j] = Math.max(dp[i][j], dp[i + 1][j - 1] + 2);
} else {
dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][n - 1];
}
}
8、最长回文子串
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
int len = 1;
String res = s.substring(0, 1);
for (int j = 1; j < n; j++) {
for (int i = j; i >= 0; i--) {
if (s.charAt(i) == s.charAt(j)) {
if (j - i <= 1) {
dp[i][j] = true;
} else {
dp[i][j] = dp[i + 1][j - 1];
}
}
if (dp[i][j] && j - i + 1 > len) {
res = s.substring(i, j + 1);
len = j - i + 1;
}
}
}
return res;
}
}