- 二叉树的最大深度
class Solution {
public int maxDepth(TreeNode root) {
if(root==null)
return 0;
int left=maxDepth(root.left);
int right=maxDepth(root.right);
return left>right?left+1:right+1;
}
}
- 平衡二叉树
这里想平衡二叉树的定义,左子树和右子树深度不超过1
同时左子树和右子树也是平衡二叉树
class Solution {
public boolean isBalanced(TreeNode root) {
if(root==null)
return true;
int deepLeft=deep(root.left);
int deepRight=deep(root.right);
int sub=deepLeft-deepRight;
if(sub>1||sub<-1)
return false;
if(!isBalanced(root.left))
return false;
if(!isBalanced(root.right))
return false;
return true;
}
public int deep(TreeNode root)
{
if(root==null)
return 0;
int left=deep(root.left);
int right=deep(root.right);
return left>right?left+1:right+1;
}
}
一样的做法,更简洁的写法:
private boolean result = true;
public boolean isBalanced(TreeNode root) {
maxDepth(root);
return result;
}
public int maxDepth(TreeNode root) {
if (root == null) return 0;
int l = maxDepth(root.left);
int r = maxDepth(root.right);
if (Math.abs(l - r) > 1) result = false;
return 1 + Math.max(l, r);
}
- 二叉树的直径
class Solution {
private int max;
public int diameterOfBinaryTree(TreeNode root) {
depth(root);
return max;
}
public int depth(TreeNode root){
if(root==null)
return 0;
int left=depth(root.left);
int right=depth(root.right);
max=Math.max(max,left+right);
return Math.max(left,right)+1;
}
}
- 翻转二叉树
递归:
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null||(root.left==null&&root.right==null))
return root;
TreeNode temp=root.right;
root.right=invertTree(root.left);
root.left=invertTree(temp);
return root;
}
}
- 合并二叉树
class Solution {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) return null;
if (t1 == null) return t2;
if (t2 == null) return t1;
TreeNode root = new TreeNode(t1.val + t2.val);
root.left = mergeTrees(t1.left, t2.left);
root.right = mergeTrees(t1.right, t2.right);
return root;
}
}
- 路径总和
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if(root==null)
return false;
if(root.right==null&&root.left==null&&root.val==sum)
return true;
return hasPathSum(root.left,sum-root.val)||hasPathSum(root.right,sum-root.val);
}
}
437路径总和 III
两种方法 双重递归
class Solution {
//双层递归
public int pathSum(TreeNode root, int sum) {
if(root==null)
return 0;
int count=path(root,sum)+pathSum(root.left,sum)+pathSum(root.right,sum); //所有结点作为根节点递归
return count;
}
public int path(TreeNode root,int sum){ //以所在根节点为递归
if(root==null)
return 0;
int count=0;
if(sum==root.val)
count++;
count+=path(root.left,sum-root.val)+path(root.right,sum-root.val);
return count;
}
}
- 另一个树的子树
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
if(s==null&&t==null)
{System.out.println("true1");
return true;}
if(s==null||t==null)
{
System.out.println("false1");
return false;
}
if(s.val==t.val)
{
isSubtree(s.left,t.left);
isSubtree(s.right,t.right);
System.out.println("true2");
return true;
}
else
{
isSubtree(s.left,t);
isSubtree(s.right,t);
}
System.out.println("false 2");
return false;
}
}
这种做法是错误的 尽管有true返回,但最终返回的是false
正确做法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
if (s == null) return false;
return isSubtree1(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t);
}
private boolean isSubtree1(TreeNode s, TreeNode t){
if(s==null&&t==null)
return true;
if(s==null||t==null)
return false;
if(s.val==t.val)
{
return isSubtree1(s.left,t.left)&&isSubtree1(s.right,t.right);
//体会这样写与isSubtree1(s.left,t.left); isSubtree1(s.right,t.right); return true的区别;
}
else
return false;
/*又可写成 if(s.val!=t.val) return false;
/* return isSubtree1(s.left,t.left)&&isSubtree1(s.right,t.right); */
}
}
- 对称二叉树
两种做法,递归和迭代:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root==null)
return true;
return isSymmetric1(root.left,root.right);
}
public boolean isSymmetric1(TreeNode left,TreeNode right){
if(left==null&&right==null)
return true;
if(left==null||right==null)
return false;
if(left.val!=right.val)
return false;
return isSymmetric1(left.left,right.right)&&isSymmetric1(left.right,right.left);
}
}
迭代:用队列实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
Queue<TreeNode> q=new LinkedList<TreeNode>();
if(root==null)
return true;
q.add(root.right);
q.add(root.left);
while(!q.isEmpty()){
TreeNode t1=q.poll();
TreeNode t2=q.poll();
if(t1==null&&t2==null) continue;
if(t1==null||t2==null) return false;
if(t1.val!=t2.val) return false;
q.add(t1.left);
q.add(t2.right);
q.add(t2.left);
q.add(t1.right);
}
return true;
}
}
- 二叉树的最小深度
class Solution {
public int minDepth(TreeNode root) {
if(root==null)
return 0;
int left=minDepth(root.left);
int right=minDepth(root.right);
if(left==0||right==0) //注意这里的情况,只有左子树或者只有右子树
return left+right+1;
return Math.min(left,right)+1;
}
}
230 Kth Smallest Element in a BST
用栈或着队列,这是一颗搜索二叉树,注意大小规则
解法一:
class Solution {
private int count=0;
private int sum=0;
public int kthSmallest(TreeNode root, int k) {
mid(root,k);
return sum;
}
private int mid(TreeNode root,int k){
if(root==null)
return 0;
mid(root.left,k);
count++;
if(count==k)
sum=root.val;
mid(root.right,k);
return 0;
}
}
解法二:
class Solution {
public int kthSmallest(TreeNode root, int k) {
Stack<TreeNode> stack=new Stack<>();
int count=0,ret=1;
while(root!=null||!stack.isEmpty()){
while(root!=null){
stack.push(root);
root=root.left;
}
root=stack.pop();
if(count<k-1){
count++;
}
else
{
ret=root.val;
break;
}
root=root.right;
}
return ret;
}
}
- 左叶子之和
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root==null)
return 0;
return sumOfLeftLeaves1(root.left,true)+sumOfLeftLeaves1(root.right,false);
}
private int sumOfLeftLeaves1(TreeNode root,boolean left)
{
if(root==null)
return 0;
int sum=0;
if(root.left==null&&root.right==null&&left) //左叶子结点
sum=root.val;
int leftv=sumOfLeftLeaves1(root.left,true);
int right=sumOfLeftLeaves1(root.right,false);
return sum+leftv+right;
}
}
- 最长同值路径
✳稍微有点难理解
class Solution {
private int count=0;
public int longestUnivaluePath(TreeNode root) {
arrowLenght(root);
return count;
}
private int arrowLenght(TreeNode node)
{
if(node==null)
return 0;
int left=arrowLenght(node.left); //父节点的值等于与左右节点比较后,左右节点继续延续(延续后只能返回左右节点的一个分支,所以函数的返回值是, Math.max(currentLeft,currentRight))
int right=arrowLenght(node.right);
int currentLeft=0,currentRight=0;
if(node.left!=null&&node.left.val==node.val)
currentLeft=left+1;
if(node.right!=null&&node.right.val==node.val)
currentRight=right+1;
count=Math.max(count,currentLeft+currentRight); //*比较一下与存储起来的值哪个大/
return Math.max(currentLeft,currentRight); //返回给父节点的值父节点不能将左右节点的延续都包括进来,
}
}
538:
解法1:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode convertBST(TreeNode root) {
TreeNode temp=root;
List<Integer> list=new ArrayList<>();
Stack<TreeNode> stack1=new Stack<>();
Stack<TreeNode> stack=new Stack<>();
while(root!=null||!stack.isEmpty()){
while(root!=null){
stack.push(root);
root=root.left;
}
root=stack.pop();
list.add(root.val);
stack1.push(root);
root=root.right;
}
// Collections.reverse(stack);
Collections.reverse(list);
while(!stack1.isEmpty()){
int sum=0;
for(int i=0;list.get(i)>stack1.peek().val;i++)
{
sum+=list.get(i);
}
System.out.println(sum);
stack1.pop().val+=sum;
}
return temp;
}
}
递归方法:
class Solution {
private sum=0;
public TreeNode convertBST(TreeNode root) {
if(root==null)
return null;
convertBST(root.right);
sum+=root.val;
root.val=sum;
convertBST(root.left);
return root;
}
}
栈方法:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode convertBST(TreeNode root) {
TreeNode temp=root;
Stack<TreeNode> stack=new Stack();
int sum=0;
while(root!=null||!stack.isEmpty()){
while(root!=null)
{
stack.push(root);
root=root.right;
}
root=stack.pop();
sum+=root.val;
root.val=sum;
root=root.left;
}
return temp;
}
}
- 打家劫舍 III
class Solution {
public int rob(TreeNode root) {
if (root == null) return 0;
int val1 = root.val;
if (root.left != null) val1 += rob(root.left.left) + rob(root.left.right);
if (root.right != null) val1 += rob(root.right.left) + rob(root.right.right);
int val2=rob(root.left)+rob(root.right); //打劫这一个加上间隔的一个多 还是直接打劫下一个左右结点
return Math.max(val1,val2);
}
}
- 二叉树中第二小的节点
class Solution {
public int findSecondMinimumValue(TreeNode root) {
//问题可以转化为求左右子树的最小值,
//如果左右子树最小值都大于根节点的值取较小的值。
//其他情况取左右子树较大的值。
if(root==null)
return -1;
if(root.left==null&&root.right==null)
return -1;
int left=root.left.val;
int right=root.right.val;
if(root.val==left)
left=findSecondMinimumValue(root.left);
if(root.val==right)
right=findSecondMinimumValue(root.right);
if(left!=-1&&right!=-1)
return Math.min(left,right);
if(left!=-1)
return left;
return right;
}
}
- 二叉树的层平均值
层次遍历
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> result=new ArrayList<>();
Queue<TreeNode> queue=new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
int size=queue.size();
double sum=0;
for(int i=0;i<size;i++){
TreeNode temp=queue.poll();
sum+=temp.val;
if(temp.left!=null)
queue.add(temp.left);
if(temp.right!=null)
queue.add(temp.right);
}
result.add(sum/size);
}
return result;
}
}
- 找树左下角的值
class Solution {
//深度搜索
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue=new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
root=queue.poll();
if(root.right!=null)queue.add(root.right);
//左结点最后取出,所以先加右结点再加左
if(root.left!=null)queue.add(root.left);
}
return root.val;
}
}
- 二叉树的前序遍历
非递归实现二叉树前序遍历,用栈的数据结构,结点先进后出
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ret = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
if (node == null) continue;
ret.add(node.val);
stack.push(node.right); // 先右后左,保证左子树先遍历
stack.push(node.left);
}
return ret;
}
- 二叉树的后序遍历
/*
非递归实现
前序遍历为 root -> left -> right,
后序遍历为 left -> right -> root。
可以修改前序遍历成为 root -> right -> left,
那么这个顺序就和后序遍历正好相反
再用reverse颠倒结果
*/
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ret=new ArrayList<>();
Stack<TreeNode> stack=new Stack<>();
if(root==null) return ret;
stack.add(root);
while(!stack.isEmpty()){
TreeNode temp=stack.pop();
ret.add(temp.val);
if(temp.left!=null)
stack.add(temp.left);
if(temp.right!=null)
stack.add(temp.right);
}
Collections.reverse(ret);
return ret;
}
}
- 二叉树的中序遍历
非递归实现
①mirrors遍历
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ret=new ArrayList<>();
TreeNode current=root;
while(current!=null){
if(current.left==null){ //如果左子树为空
ret.add(current.val); //假如当前结点并进入右边节点
current=current.right;
}
else{ //左子树不为空,找他的前序结点
TreeNode temp=current.left;
while(temp.right!=null&&temp.right!=current){
//找最右结点,并且不是指向current的最右结点
temp=temp.right;
}
if(temp.right==null){ //最右结点还没指向current时
temp.right=current;
current=current.left; //进入他的左子树
}
else{ //要是指向了当前节点自己
temp.right=null;
ret.add(current.val); //打印curr的值
current=current.right; //左边遍历完毕 ,遍历右边
}
}
}
return ret;
}
}
②
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ret = new ArrayList<>();
if (root == null) return ret;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
//要先加入所有的左孩子结点
stack.push(cur);
cur = cur.left;
}
TreeNode node = stack.pop();
ret.add(node.val);
cur = node.right;
}
return ret;
}
- 修剪二叉搜索树
class Solution {
public TreeNode trimBST(TreeNode root, int L, int R) {
if(root==null) return null;
if(root.val>R) return trimBST(root.left,L,R);
if(root.val<L) return trimBST(root.right,L,R);
root.left=trimBST(root.left,L,R);
root.right=trimBST(root.right,L,R);
return root;
}
}
- 把二叉搜索树转换为累加树
①迭代解法:
class Solution {
public TreeNode convertBST(TreeNode root) {
TreeNode temp=root;
Stack<TreeNode> stack=new Stack();
int sum=0;
while(root!=null||!stack.isEmpty()){
//按从大到小的顺序出栈就可以
while(root!=null)
{
stack.push(root);
root=root.right;
}
root=stack.pop();
sum+=root.val;
root.val=sum;
root=root.left;
}
return temp;
}
}
②递归解法:
private int sum = 0;
public TreeNode convertBST(TreeNode root) {
traver(root);
return root;
}
private void traver(TreeNode node) {
if (node == null) return;
traver(node.right);
sum += node.val;
node.val = sum;
traver(node.left);
}
- 二叉搜索树的最近公共祖先
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root.val>p.val&&root.val>q.val)
return lowestCommonAncestor(root.left,p,q);
if(root.val<p.val&&root.val<q.val)
return lowestCommonAncestor(root.right,p,q);
return root;
}
}
- 二叉树的最近公共祖先
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);
return left == null ? right : right == null ? left : root;
}
}
- 将有序数组转换为二叉搜索树
分治算法
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return toBST(nums, 0, nums.length - 1);
}
private TreeNode toBST(int[] nums, int sIdx, int eIdx){
if (sIdx > eIdx) return null;
int mIdx = (sIdx + eIdx) / 2;
TreeNode root = new TreeNode(nums[mIdx]);
root.left = toBST(nums, sIdx, mIdx - 1);
root.right = toBST(nums, mIdx + 1, eIdx);
return root;
}
}
- 有序链表转换二叉搜索树
跟上一题相似,快慢指针找出链表的中点
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if(head==null)
return null;
if (head.next == null)
return new TreeNode(head.val);
ListNode pre=findMid(head);
ListNode mid=pre.next;
pre.next=null;
TreeNode root=new TreeNode(mid.val);
root.left=sortedListToBST(head);
root.right=sortedListToBST(mid.next);
return root;
}
public ListNode findMid(ListNode head){
ListNode slow=head,fast=head.next;
ListNode pre=head;
while(fast!=null&&fast.next!=null){
pre=slow;
slow=slow.next;
fast=fast.next.next;
}
return pre;
}
}
- 两数之和 IV - 输入 BST
其他解法:找中子数
class Solution {
public boolean findTarget(TreeNode root, int k) {
Set<Integer> set=new HashSet<>();
return helper(set,root,k);
}
public boolean helper(Set set,TreeNode root,int k){
if(root==null)
return false;
if(set.contains(k-root.val))
return true;
set.add(root.val);
return helper(set,root.left,k)||helper(set,root.right,k);
}
}
- 二叉搜索树的最小绝对差
class Solution {
private int min=Integer.MAX_VALUE;
private TreeNode pre=null;
public int getMinimumDifference(TreeNode root) {
helper(root);
return min;
}
public void helper(TreeNode root){
if(root==null)
return;
helper(root.left);
if(pre!=null) {
//按递增顺序遍历的,pre结点的值总是小于root结点
min=Math.min(min,root.val-pre.val);
}
pre=root; ///上一步的结点
helper(root.right);
return;
}
}
- 二叉搜索树中的众数
class Solution {
private int curCnt = 1;
private int maxCnt = 1;
private TreeNode preNode = null;
List<Integer> list=new ArrayList<>();
public int[] findMode(TreeNode root) {
findList(root);
int[] ret = new int[list.size()];
int idx = 0;
for (int num : list) {
ret[idx++] = num;
}
return ret;
}
private void findList(TreeNode root){
if(root==null)
return;
findList(root.left);
if(preNode!=null)
if(root.val==preNode.val)
curCnt++;
else
curCnt=1;
if(curCnt==maxCnt)
list.add(root.val);
if(curCnt>maxCnt)
{
maxCnt=curCnt;
list.clear();
list.add(root.val);
}
preNode=root;
findList(root.right);
return;
}
}
- 实现 Trie (前缀树)
⭐有点难,有空再code一下
class TreeNode{
public TreeNode[] children=new TreeNode[26];
public boolean isEnd;
/*public TreeNode(){//
children = new TreeNode[26];//子节点数组长度26,0:‘a’,1:‘b’.....
isEnd= false;
}*/
}
class Trie {
TreeNode root;
private int count=0;
// Trie next;
/** Initialize your data structure here. */
public Trie() {
root=new TreeNode();
}
/** Inserts a word into the trie. */
public void insert(String word) {
TreeNode p=root;
for (int i = 0; i <word.length(); i++) {
char curent=word.charAt(i);
if(p.children[curent-'a']==null){
p.children[curent-'a']=new TreeNode();
}
p=p.children[curent-'a'];
}
p.isEnd=true;
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
TreeNode p=root;
for(int i=0;i<word.length();i++)
{
char curent=word.charAt(i);
if(p.children[curent-'a']!=null)
p=p.children[curent-'a'];
else
return false;
}
return p.isEnd;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TreeNode p=root;
for(int i=0;i<prefix.length();i++)
{
char curent=prefix.charAt(i);
if(p.children[prefix.charAt(i)-'a']!=null)
p=p.children[curent-'a'];
else
return false;
}
if(p.isEnd==true)
count++;
getCount(p);
System.out.println(count);
return true;
}
public void getCount(TreeNode p) {
if(p==null)
return;
for(int i=0;i<26;i++){
if(p.children[i]!=null){
if(p.children[i].isEnd==true)
{
count++;
continue;
}
else
getCount(p.children[i]);
}
}
return;
}
}
- 键值映射
⭐有点难
class MapSum {
private class Node {
Node[] child = new Node[26];
int value;
}
private Node root = new Node();
public MapSum() {
}
public void insert(String key, int val) {
insert(key, root, val);
}
private void insert(String key, Node node, int val) {
if (node == null) return;
if (key.length() == 0) {
node.value = val;
return;
}
int index = indexForChar(key.charAt(0));
if (node.child[index] == null) {
node.child[index] = new Node();
}
insert(key.substring(1), node.child[index], val);
}
public int sum(String prefix) {
return sum(prefix, root);
}
private int sum(String prefix, Node node) {
if (node == null) return 0;
if (prefix.length() != 0) {
int index = indexForChar(prefix.charAt(0));
return sum(prefix.substring(1), node.child[index]);
}
int sum = node.value;
for (Node child : node.child) {
sum += sum(prefix, child);
}
return sum;
}
private int indexForChar(char c) {
return c - 'a';
}
}