1、矩阵中的路径
class Solution {
public boolean exist(char[][] board, String word) {
char[] words = word.toCharArray();
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[0].length; j++) {
if(dfs(board, words, i, j, 0)) return true;
}
}
return false;
}
boolean dfs(char[][] board, char[] word, int i, int j, int k) {
if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false;
if(k == word.length - 1) return true;
board[i][j] = '\0';
boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) ||
dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);
board[i][j] = word[k];
return res;
}
}
作者:Krahets
链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/58d5vh/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2、机器人的运动范围
这种在矩阵中遍历的题目,不同的地方就是递归退出的条件以及返回值。
class Solution {
public int movingCount(int m, int n, int k) {
int area = 0;
boolean[][] visited = new boolean[m][n];
return dfs(0,0,m,n,k,visited);
}
private int dfs(int i,int j,int m,int n,int k,boolean[][] visited){
//递归退出条件
if(i < 0 || i >= m || j < 0 || j >= n || (i%10)+(i/10)+(j%10)+(j/10) > k || visited[i][j]){
return 0;
}
//遍历过的地方做标记
visited[i][j] = true;
int n1 = dfs(i-1,j,m,n,k,visited);
int n2 = dfs(i+1,j,m,n,k,visited);
int n3 = dfs(i,j-1,m,n,k,visited);
int n4 = dfs(i,j+1,m,n,k,visited);
return n1+n2+n3+n4+1;
}
}
3、树的子结构
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
if(A == null || B == null){return false;}
return isSame(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);
}
public boolean isSame(TreeNode A,TreeNode B){
//好像题意并不需要B和A的子结构完全一样
//注意!!这里B==null的判断一定要放在前面!!
if(B == null){return true;}
if(A == null){return false;}
return isSame(A.left,B.left) && isSame(A.right,B.right) && (A.val == B.val);
}
}
class Solution {
public int maximumRemovals(String s, String p, int[] removable) {
// List<Character> s1 = s.toCharArray().chars().mapToObj(c->(char) c).collect(Collectors.toList());
if(s.length() == 0 || s.length() < p){return 0;}
if(removable.length == 0){return subSeq(list,p,)}
char[] ch = s.toCharArray();
List<Character> list = new ArrayList<>();
for(int i = 0;i < ch.length;i++){
list.add(ch[i]);
}
int i = 0;
for(;i < removable.length;i++){
if(!subSeq(list.remove(removable[i]),p,start)){
break;
}
}
return i;
}
private boolean subSeq(List<Character> list,String p){
if(list.size() < p){return false;}
for(int i = start;i < p.length();i++){
int index = list.indexOf(p.charAt(i));
if(index == -1){
return false;
}else{
subSeq(list.subList(index+1,list.size()),p.substring(start+1,p.length));
}
}
return true;
}
}
4、二叉树的镜像
输出给定二叉树的镜像
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if(root == null){return root;}
if(root.left == null && root.right == null){return root;}
swap(root);
return root;
}
private void swap(TreeNode root){
if(root == null){return;}
TreeNode node = root.left;
root.left = root.right;
root.right = node;
swap(root.left);
swap(root.right);
}
}
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if(root == null) return null;
TreeNode tmp = root.left;
root.left = mirrorTree(root.right);
root.right = mirrorTree(tmp);
return root;
}
}
5、对称的二叉树
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null){return true;}
return judge(root.left,root.right);
}
private boolean judge(TreeNode A,TreeNode B){
if(A == null && B == null){return true;}
if(A == null || B == null){return false;}
return judge(A.left,B.right) && judge(A.right,B.left) && A.val == B.val;
}
}
6、 从上到下打印二叉树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int[] levelOrder(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null){return new int[0];}
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
int size = q.size();
for(int i = 0;i < size;i++){
TreeNode node = q.poll();
list.add(node.val);
if(node.left!=null){
q.add(node.left);
}
if(node.right!=null){
q.add(node.right);
}
}
}
return list.stream().mapToInt(Integer::intValue).toArray();
}
}
7、从上到下打印二叉树 II
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if(root == null){return res;}
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
int size = q.size();
List<Integer> tmp = new ArrayList<>();
//注意:循环这里第二个条件不能用q.size(),因为将左右节点加进去之后,q的大小发生了变化
for(int i = 0;i < size;i++){
TreeNode node = q.poll();
tmp.add(node.val);
if(node.left != null){
q.add(node.left);
}
if(node.right !=null){
q.add(node.right);
}
}
res.add(tmp);
}
return res;
}
}
8、从上到下打印二叉树 III
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
boolean flag = true;//true代表向右,false代表向左
List<List<Integer>> res = new ArrayList<>();
if(root == null){return res;}
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
int size = q.size();
List<Integer> tmp = new ArrayList<>();
for(int i = 0;i < size;i++){
TreeNode node = q.poll();
tmp.add(node.val);
if(node.left !=null){
q.add(node.left);
}
if(node.right !=null){
q.add(node.right);
}
}
if(flag){
res.add(tmp);
flag = false;
}else{
Collections.reverse(tmp);
res.add(tmp);
flag = true;
}
}
return res;
}
}
9、二叉树中和为某一值的路径
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int target) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> tmp = new ArrayList<>();
if(root == null){return res;}
dfs(root,target,res,tmp);
return res;
}
private void dfs(TreeNode root,int target,List<List<Integer>> res,List<Integer> tmp){
//必须走到叶子节点
if(root == null){return;}
tmp.add(root.val);
target -= root.val;
if(root.left == null && root.right == null && target == 0){
res.add(new ArrayList(tmp));
}
dfs(root.left,target,res,tmp);
dfs(root.right,target,res,tmp);
tmp.remove(tmp.size()-1);
}
}
——————————————————————————————————————————————6.14
10、二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
11、序列化二叉树
和层序遍历不同的是,这里的节点假如为空,也要加入序列中
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root == null){return "[]";}
StringBuilder res = new StringBuilder("[");
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
if(node!=null){
res.append(node.val+",");
queue.add(node.left);
queue.add(node.right);
}else{
res.append("null,");
}
}
//把最末尾的逗号去掉
res.deleteCharAt(res.length()-1);
res.append("]");
// System.out.println(res.toString());
return res.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if(data.equals("[]")){return null;}
//首先得将节点值剥离
String[] nodeVal = data.substring(1,data.length()-1).split(",");//字符串首尾都是括号
//建立根节点
TreeNode root = new TreeNode(Integer.parseInt(nodeVal[0]));
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
int i = 1;//从第二个数组值开始构建根节点的左右子树
while(!q.isEmpty()){
TreeNode node = q.poll();
if(!nodeVal[i].equals("null")){
node.left = new TreeNode(Integer.parseInt(nodeVal[i]));
q.add(node.left);
}
i++;
if(!nodeVal[i].equals("null")){
node.right = new TreeNode(Integer.parseInt(nodeVal[i]));
q.add(node.right);
}
i++;
}
return root;
}
}
12、字符串的排列
全排列
class Solution{
StringBuilder sb = new StringBuilder();
public String[] permutation(String s) {
if(s.length() == 0){return new String[0];}
List<String> res = new ArrayList<>();
boolean[] used = new boolean[s.length()];
char[] str = s.toCharArray();
Arrays.sort(str);
dfs(str,used,res,sb);
String[] st =new String[res.size()];
for(int i = 0;i < res.size();i++){
st[i] = res.get(i);
}
return st;
}
private void dfs(char[] str,boolean[] used,List<String> res,StringBuilder sb){
//递归出口
if(sb.length() == str.length){
res.add(sb.toString());
return;
}
for(int i= 0;i < str.length;i++){
if(!used[i]){
if(i > 0 && str[i] == str[i-1] && !used[i-1]){
continue;
}else{
sb.append(str[i]);
used[i] = true;
dfs(str,used,res,sb);
used[i] = false;
sb.deleteCharAt(sb.length()-1);
}
}
}
}
}
13、二叉搜索树的第K大节点
倒着中序遍历——右中左
class Solution {
public int kthLargest(TreeNode root, int k) {
List<Integer> res = new ArrayList<>();
inOrder(root,k,res);
return res.get(k-1);
}
private void inOrder(TreeNode root,int k,List<Integer> res){
if(root == null){return;}
inOrder(root.right,k,res);
res.add(root.val);
if(res.size() == k){return;}
inOrder(root.left,k,res);
}
}
14、二叉树的深度
class Solution {
public int maxDepth(TreeNode root) {
if(root == null){return 0;}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left,right)+1;
}
}
15、平衡二叉树
递归检查二叉树的每个节点的左右子树差即可
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null){return true;}
//该节点的左右子树最大深度差
if(Math.abs(judgeNode(root.left) - judgeNode(root.right)) > 1){
return false;
}
//递归遍历左右子树的每个节点
return isBalanced(root.left) && isBalanced(root.right);
}
private int judgeNode(TreeNode root){
if(root == null){return 0;}
int left = judgeNode(root.left);
int right = judgeNode(root.right);
return Math.max(left,right)+1;
}
16、求1 + 2 + … + n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
class Solution{
int res = 0;
public int sumNums(int n) {
boolean x = n>1&& sumNums(n-1)>0;
res+=n;
return res;
}
}
//动态规划
class Solution {
public int sumNums(int n) {
int dp[] = new int[n+1];
if(n == 0 || n == 1){return n;}
dp[1] = 1;
for(int i = 2;i < n+1;i++){
dp[i] = dp[i-1]+i;
}
return dp[n];
}
}
参考链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/9h1gyt/
17、I. 二叉搜索树的最近公共祖先
左右子树递归:
假如都在左子树,那么先找到谁谁就是祖先;
假如都在右子树,那么先找到谁谁就是祖先;
假如一个在左子树,一个在右子树,那么公共祖先为根节点。
注意:可以利用二叉搜索树的值大小特性
//递归解法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null){return null;}
if(root == p || root == q){return root;}
if(root.val < p.val && root.val < q.val) // p,q 都在 root 的右子树中
root = lowestCommonAncestor(root.right,p,q); // 遍历至右子节点
else if(root.val > p.val && root.val > q.val) // p,q 都在 root 的左子树中
root = lowestCommonAncestor(root.left,p,q); // 遍历至左子节点
return root;
}
}
//迭代解法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root != null) {
if(root.val < p.val && root.val < q.val) // p,q 都在 root 的右子树中
root = root.right; // 遍历至右子节点
else if(root.val > p.val && root.val > q.val) // p,q 都在 root 的左子树中
root = root.left; // 遍历至左子节点
else break;
}
return root;
}
}
作者:Krahets
链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/5793vc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
18、二叉树的最近公共祖先
注意:这个题是二叉树,不是二叉搜索树
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == p || root == q){return root;}
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
//两者都不为空
if(left != null && right!=null){
return root;
}
//两者都为空
if(left == null && right == null){
return null;
}
return left == null?right:left;
}
}