数据结构之树(其三)
先从上至下找到该节点,再把该节点一层层地传上来。
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; } }

浙公网安备 33010602011771号