数据结构之树(其三)

二叉搜索树中的搜索

先从上至下找到该节点,再把该节点一层层地传上来。

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null || root.val == val) return root;
        if (root.val > val) return searchBST(root.left, val);
        if (root.val < val) return searchBST(root.right, val);
        return root;
    }
}

 

二叉搜索树的插入操作 题目 解析

递归每一层传是自己。相当于没有传递。可以和上一题的递归对比一下。第二个解法相当于第三个解法的简写。

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) return new TreeNode(val);
        TreeNode temp = root;
        while (temp != null) {
            if (temp.val > val) {
                if (temp.left == null) {
                    temp.left = new TreeNode(val);
                    break;
                }
                else{
                    temp = temp.left;
                }
            }
            else if (temp.val < val) {
                if(temp.right == null) {
                    temp.right = new TreeNode(val);
                    break;
                }
                else {
                    temp = temp.right;
                }
            }
        }
        return root;
    }
}
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) return new TreeNode(val);
        if (root.val > val) root.left = insertIntoBST(root.left, val);
        if (root.val < val) root.right = insertIntoBST(root.right, val);
        return root;
    }
}
class Solution {
    private TreeNode cur;
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) return new TreeNode(val);
        build(root, val);
        return root;
    }
    public void build(TreeNode root, int val) {
        if (root == null) {
            if (cur.val > val) cur.left = new TreeNode(val);
            else cur.right = new TreeNode(val);
            return;
        }
        cur = root;
        if (root.val > val) build(root.left, val);
        if (root.val < val) build(root.right, val);
    }
}

 

二叉搜索树的删除操作 题目 解析

要注意的是删除时的五种情况,依然是返回每一层的节点。

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) return root;
        if (root.val == key) {
            if(root.left == null && root.right == null) return null;
            else if (root.left == null) return root.right;
            else if (root.right == null) return root.left;
            else {
                TreeNode temp = root.left;
                TreeNode cur = root.right;
                root = root.right;
                while(root.left != null) {
                    root = root.left;
                }
                root.left = temp;
                return cur;
            }
        }
        root.left = deleteNode(root.left, key);
        root.right = deleteNode(root.right, key);
        return root;
    }
}

 

将有序数组转换成二叉搜索树 题目 解析

分治,左闭右闭。(左闭右开也可以)

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return build(nums, 0, nums.length-1);
    }
    public TreeNode build(int[] nums, int l, int r) {
        if (l > r) return null;
        int mid = l + (r - l) / 2;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = build(nums, l, mid-1);
        root.right = build(nums, mid+1, r);
        return root;
    }
}

 有序链表转换二叉搜索树

因为链表的特性,用左闭又开会更好

class Solution {
    public TreeNode sortedListToBST(ListNode head) {
       return build(head, null);
    }
    public TreeNode build(ListNode p, ListNode q) {
        if (p == q) return null;
        ListNode mid = getmid(p, q);
        TreeNode node = new TreeNode(mid.val);
        node.left = build(p, mid);
        node.right = build(mid.next, q);
        return node; 
    } 
    public ListNode getmid(ListNode p, ListNode q) {
        ListNode fast = p;
        ListNode low = p;
        while (fast != q && fast.next != q) {
            fast = fast.next.next;
            low = low.next;
        }
        return low;
    }
}

 

验证二叉搜索树 题目 解析

二叉搜索树在中序遍历时是从小到大排序的。

class Solution {
    long front = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        boolean left = isValidBST(root.left);
        if (front >= root.val) return false;
        else front = root.val;
        boolean right = isValidBST(root.right);
        return left && right;
    }
}
class Solution {
    private List<Integer> ans = new ArrayList<>();
    public boolean isValidBST(TreeNode root) {
        inorder(root);
        for (int i = 0; i < ans.size()-1; i++) {
            if (ans.get(i) >= ans.get(i+1)) return false;
        }
        return true;
    }
    public void inorder(TreeNode root) {
        if (root == null) return;
        inorder(root.left);
        ans.add(root.val);
        inorder(root.right);
    }
}

 

二叉搜索树的最小绝对差 题目 解析

如何保留前一个节点?

class Solution {
    private TreeNode pre;
    private int min = Integer.MAX_VALUE;
    public int getMinimumDifference(TreeNode root) {
        get(root);
        return min;
    }
    private void get(TreeNode root) {
        if (root == null) return;
        get(root.left);
        if (pre != null) {
            min = Math.min(min, root.val - pre.val);
        }
        pre = root;
        get(root.right);
    }
}

 

二叉搜索树中的众树 题目 解析

难住我的竟是List转数组?

class Solution {
    private List<Integer>ans = new LinkedList<>();
    int count = 0;
    int max = 0;
    TreeNode pre;
    public int[] findMode(TreeNode root) {
        bst(root);
        int[] a = new int[ans.size()];
        for (int i = 0; i < ans.size(); i++) {
            a[i] = ans.get(i);
        }
        return a;
    }
    public void bst(TreeNode root) {
        if (root == null) return;
        bst(root.left);
        if (count == 0 || root.val == pre.val) {
            count++;
        }
        else count = 1;
        pre = root;
        if (max == count) {
            ans.add(root.val);
        }
        if (count > max) {
            max = count;
            ans.clear();
            ans.add(root.val);
        }
        bst(root.right);
    }
}

 

二叉树的最近公共祖先 题目  解析  解析

底部不是空就是p,q。向上移的过程中如果传来空就舍弃,将p,q节点的祖先向上传递。如果左右节点都不为空,那么就是公共祖先啦。再往上因为另一边为空,

所以最近公共祖先一直往上传,直到顶部。

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || p == root || q == root) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if (left == null && right != null) return right;
        if (right == null && left != null) return left;
        if (left == null && right == null) return null;
        return root;
    }
}

 

二叉搜索树的最近公共祖先 题目 解析

自上而下,利用二叉搜索树的特性。

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        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 trimBST(TreeNode root, int low, int high) {
        if (root == null) return null;
        if (root.val < low) {
            root = trimBST(root.right, low, high);
        }
        else if (root.val > high) {
            root = trimBST(root.left, low, high);
        }
        else {
        root.left = trimBST(root.left, low, high);
        root.right = trimBST(root.right, low, high);
        }
        return root;
    }
}

 

把二叉树转换成累加树 题目 解析

我一开始把cur=root放在最前面了,那是不对的。因为cur应该记录的是改变后的节点。函数里面的root怎么变,如果不返回,只是本次调用里面变化了,外部是没有变的,要想外部变就必须返回。cur是函数之外的,你可以把它当作是全局变量。

class Solution {
    private TreeNode cur;
    public TreeNode convertBST(TreeNode root) {
        if (root == null) return null;
        root.right = convertBST(root.right);
        if (cur != null) root.val += cur.val;
        cur = root;
        root.left = convertBST(root.left);
        return root;
    }
}

 

posted @ 2020-11-11 18:19  CPJ31415  阅读(105)  评论(0)    收藏  举报