刷题笔记-树

刷题笔记-树

2021年4月8日

  1. Leetcode - 148 链表排序

标签: 排序,链表排序, 归并排序

class Solution {
    // 归并排序
    public ListNode sortList(ListNode head) {
        return sortList(head, null);
        
    }

    private ListNode sortList(ListNode head, ListNode tail){
        if(head == null){
            return head;
        }

        if(head.next == tail){
            head.next = null;
            return head;
        }
        ListNode slow = head, fast = head;
        while(fast != tail){
            slow = slow.next;
            fast = fast.next;
            if(fast != tail){
                fast = fast.next;
            }
        }
        ListNode mid = slow;
        ListNode list1 = sortList(head, mid);
        ListNode list2 = sortList(mid, tail);
        return merge2(list1, list2);
    }

    public ListNode merge1(ListNode head1, ListNode head2) {
        ListNode dummyHead = new ListNode(0);
        ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
        while (temp1 != null && temp2 != null) {
            if (temp1.val <= temp2.val) {
                temp.next = temp1;
                temp1 = temp1.next;
            } else {
                temp.next = temp2;
                temp2 = temp2.next;
            }
            temp = temp.next;
        }
        if (temp1 != null) {
            temp.next = temp1;
        } else if (temp2 != null) {
            temp.next = temp2;
        }
        return dummyHead.next;
    }


    private ListNode merge2(ListNode list1, ListNode list2){
        if(list1 == null){
            return list2;
        }
        if(list2 == null){
            return list1;
        }
        if(list1.val > list2.val){
            list2.next = merge2(list2.next, list1);
            return list2;
        }else{
            list1.next = merge2(list1.next, list2);
            return list1;
        }
    }      
}
  1. 剑指 Offer 28. 对称的二叉树 - 力扣(LeetCode)

标签: 二叉树

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return isSymmetric(root, root);
    }
    
    private boolean isSymmetric(TreeNode root1, TreeNode root2){
        if(root1 == null && root2 == null){
            return true;
        }

        if(root1 == null || root2 == null){
            return false;
        }

        if(root1.val != root2.val){
            return false;
        }

        return isSymmetric(root1.left, root2.right) && isSymmetric(root1.right, root2.left);

    }
}
  1. 剑指 Offer 36. 二叉搜索树与双向链表 - 力扣(LeetCode)

标签:二叉搜索树

方法一: 迭代(中序遍历)

class Solution {
    public Node treeToDoublyList(Node root) {
        // 迭代
        if(root == null){
            return root;
        }
        Node dummy = new Node();
        Node cur = dummy;
        Deque<Node> stack = new LinkedList<>();
        while(root != null || !stack.isEmpty()){
            while(root != null){
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            root.left = cur;
            cur.right = root;
            cur = cur.right;
            root = root.right;
        }
        Node node = dummy.right;
        node.left = cur;
        cur.right = node;
        return node;
    }
}

方法二: 递归(中序遍历)

class Solution {
    public Node dummy = new Node();
    public Node cur = dummy;
    public Node treeToDoublyList(Node root) {
        if(root == null){
            return root;
        }
        // 递归
        inorderTraversal(root);
        Node node = dummy.right;
        node.left = cur;
        cur.right = node;
        return node;

    }

    private void inorderTraversal(Node root){
        if(root == null){
            return;
        }
        inorderTraversal(root.left);
        cur.right = root;
        root.left = cur;
        cur = cur.right;
        inorderTraversal(root.right);
    }
}
  1. 剑指 Offer 38. 字符串的排列 - 力扣(LeetCode)

标签: 深度搜索,回溯算法

方法一: DFS

class Solution {
    List<String> res = new ArrayList<>();
    public String[] permutation(String s) {

        int len = s.length();
        if (len == 0) {
            return new String[0];
        }
        char[] charArray = s.toCharArray();
        Arrays.sort(charArray);
        StringBuilder path = new StringBuilder();
        boolean[] used = new boolean[len];
        dfs(charArray, path, used);
        return res.toArray(new String[res.size()]);
        
    }

    private void dfs(char[] charArray, StringBuilder path,  boolean[] used){
        int len = charArray.length;
        // 保存数据
        if(len == path.length()){
            res.add(path.toString());
            return;
        }
        for(int i=0; i<len; i++){
            if(!used[i]){
                // 剪枝
                if(i > 0 && charArray[i] == charArray[i-1] && !used[i-1]){
                    continue;
                }
                path.append(charArray[i]);
                used[i] = true;
                dfs(charArray, path, used);
                path.deleteCharAt(path.length() - 1);
                used[i] = false;
            }

        }
    }
}
  1. 剑指 Offer 32 - I. 从上到下打印二叉树 - 力扣(LeetCode)

标签:广度优先搜索

2021年4月9日

  1. 剑指 Offer 27. 二叉树的镜像 - 力扣(LeetCode)[二叉树]

方法二: 递归

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;
    }
}

方法一: 迭代

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null){
            return root;
        }
        // 层序遍历迭代交换左右子树
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode node  = queue.poll();
            TreeNode tmp = node.left;
            node.left = node.right;
            node.right = tmp;
            if(node.left != null){
                queue.offer(node.left);
            } 
            if(node.right != null){
                queue.offer(node.right);
            }
        }
        return root;
    }
}
  1. Leetcode - 112 路径总和 - 力扣(LeetCode)[二叉树]

方法一:递归

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null){
            return false;
        }
        if (root.left == null && root.right == null) {
            return targetSum == root.val;
        }
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }
}

方法二:BFS(迭代) 层序遍历

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        // BFS 
        if(root == null){
            return false;
        }
        Queue<TreeNode> nodeQ  = new LinkedList<>();
        Queue<Integer> sumQ = new LinkedList<>();
        nodeQ.offer(root);
        sumQ.offer(root.val);
        while (!nodeQ.isEmpty()){
            TreeNode node = nodeQ.poll();
            int sum = sumQ.poll();
            if(node.left == null && node.right == null && sum == targetSum){
                return true;
            }
            if(node.left != null){
                nodeQ.offer(node.left);
                sumQ.offer(sum + node.left.val);
            }
            if(node.right != null){
                nodeQ.offer(node.right);
                sumQ.offer(sum + node.right.val);
            }
        }
        return false;
    } 
}
  1. Leetcode - 113 路径总和 II - 力扣(LeetCode)[二叉树]

方法一: DFS

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        int sum = 0;
        def(root, targetSum, sum);
        return res;
    }

    private void dfs(TreeNode root, Integer targetSum, int sum) {
        if(root == null){
            return;
        }
        sum += root.val;
        path.add(root.val);
        if(root.left == null && root.right == null && sum == targetSum){
            res.add(new ArrayList(path));
        } 
        def(root.left, targetSum, sum);
        def(root.right, targetSum, sum);
        sum -= root.val;
        path.remove(path.size()-1);
    }
}

方法二: BFS

class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> res = new ArrayList<>();
        // BFS 
        if (root == null) {
            return res;
        }
        Queue<TreeNode> nodeQ = new LinkedList<>();
        Queue<List<Integer>> pathQ = new LinkedList<>();
        Queue<Integer> sumQ = new LinkedList<>();
        nodeQ.offer(root);
        List<Integer> pathR = new ArrayList<Integer>();
        pathR.add(root.val);
        pathQ.offer(pathR);
        sumQ.offer(root.val);
        while (!nodeQ.isEmpty()) {
            TreeNode node = nodeQ.poll();
            List<Integer> path = pathQ.poll();
            int sum = sumQ.poll();
            if (node.left == null && node.right == null && sum == targetSum) {
                res.add(path);
            }
            if (node.left != null) {
                List<Integer> newList = new ArrayList<>(path);
                newList.add(node.left.val);
                nodeQ.offer(node.left);
                pathQ.offer(newList);
                sumQ.offer(sum + node.left.val);

            }
            if (node.right != null) {
                List<Integer> newList = new ArrayList<>(path);
                newList.add(node.right.val);
                nodeQ.offer(node.right);
                pathQ.offer(newList);
                sumQ.offer(sum + node.right.val);
            }
        }
        return res;

    }
}
  1. Leetcode - 437 路径总和 III - 力扣(LeetCode)[二叉树]

方法一: 双重递归(DFS + DFS)

class Solution {
    public int pathSum(TreeNode root, int targetSum) {
        if(root == null){
            return 0;
        }
        int count = countPath(root, targetSum);
        count += pathSum(root.left, targetSum);
        count += pathSum(root.right, targetSum);
        return count;
    }

    /**
    * 递归计算以树为根节点的路径条数之合;
    */
    private int countPath(TreeNode root, int sum){
        if(root == null){
            return 0;
        }
        int count = 0;
        if(root.val == sum){
            count ++;
        }
        count += countPath(root.left, sum - root.val);
        count += countPath(root.right, sum - root.val);
        return count;

    }
}
  1. Leetcode - 514 自由之路 - 力扣(LeetCode)[深度搜索]

方法一: DFS + 记忆

class Solution {
    
    HashMap<Character, List<Integer>> map; // 用于存储ring里面字符的索引位置
    String ring;
    String key;
    
    private int[][] memo;
    public int findRotateSteps(String ring, String key) {
        this.ring = ring;
        this.key = key;
        map = new HashMap<>();
        int m = key.length();
        int n = ring.length();
        this.memo = new int[m][n];

        for(int i = 0; i < ring.length(); i++){
            Character r =  ring.charAt(i);
            List<Integer> list = map.getOrDefault(r, new ArrayList<Integer>());
            list.add(i);
            map.put(r, list);
        }

        return  dfs(0, 0);
    }

    private int dfs(int ringI, int keyI){
        if(keyI == key.length()){
            return 0;
        }

        if(memo[keyI][ringI] != 0){
            return memo[keyI][ringI];
        }

        List<Integer> list = map.get(key.charAt(keyI));
        int res = Integer.MAX_VALUE;
        for(Integer index : list){
            // 计算当前ring到目标key的最小步骤
            int minCur = Math.min(Math.abs(ringI - index),ring.length() - Math.abs(ringI - index));
            // 计算下一key到需要的最小步骤
            int minNext = dfs(index, keyI+1);
            res = Math.min(res, minCur + minNext);
        }
        memo[keyI][ringI] = res + 1;
        return res + 1;
    }
}

2021年4月10日

  1. Leetcode - 912 排序数组 - 力扣(LeetCode)[快速排序]

方法一: 堆排序

class Solution {
    public int[] sortArray(int[] nums) {
        // 堆排序
        PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>((o1, o2) -> o1 - o2);
        for(int num : nums){
             minHeap.offer(num);
        }
        int i = 0;
        while(!minHeap.isEmpty()){
            nums[i++] = minHeap.poll();
        }
        return nums;
    }
}

方法二: 快排

class Solution {
    int[] nums;
    public int[] sortArray(int[] nums) {
        // 快排
        this.nums = nums;
        quickSort(0, nums.length);
        return nums;
    }

    private void quickSort(int begin, int end){
        if(end - begin < 2){
            return;
        }
        // 获取轴点位置
        int pivot = pivotIndex(begin, end);
        // 递归
        quickSort(begin, pivot);
        quickSort(pivot + 1, end);

    }

    private int pivotIndex(int begin, int end){
        swap(begin, begin + (int)(Math.random() * (end - begin)));
        int pivot = nums[begin];
        end--;
        while(begin < end){
            while(begin < end){
                if(pivot < nums[end]){
                    end--;
                }else{
                    nums[begin++] = nums[end];
                    break;
                }
            }
            while(begin < end){
                if(pivot > nums[begin]){
                    begin++;
                }else{
                    nums[end--] = nums[begin];
                    break;
                }
            }
        }
        nums[begin] = pivot;
        return begin;

    }

    private void swap(int index1, int index2){
        int tmp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = tmp;
    }
}
  1. Leetcode - 967 连续差相同的数字 - 力扣(LeetCode)[广度优先]
class Solution {
    int n;
    int k;
    List<Integer> list;
    public int[] numsSameConsecDiff(int n, int k) {
        this.n = n;
        this.k = k;
        this.list = new ArrayList<>();
        if(n == 1){
            return new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        }
        for(int i = 1; i <= 9; i++){
            dfs(i);
        }
        int[] res = new int[list.size()];
        int i = 0;
        for(int r : list){
            res[i++] = r;
        }
        return res;
    }
    private void dfs(int digit){
        if((int)(Math.log10(digit)) + 1 == n){
            list.add(digit);
            return;
        }
        int pre = digit % 10; // 数字末位
        if(pre >= k){
            dfs(10 * digit + pre - k);  // 后一位追加上次末位左边
        }
        if(k != 0 && pre + k <= 9){
            dfs(10 * digit + pre + k); // 后一位追加上次末位右边
        }
    }
}

2021年4月11日

  1. 剑指 Offer 54. 二叉搜索树的第k大节点 - 力扣(LeetCode)

方法一: 迭代反向中序遍历(从大到小排)

class Solution {
    public int kthLargest(TreeNode root, int k) {
        if(root == null){
            return 0;
        }
        Deque<TreeNode> stack = new LinkedList<>();
        while(root != null || !stack.isEmpty()){
            while(root != null){
                stack.push(root);
                root = root.right;
            }
            root = stack.pop();
            if(--k == 0){
                return root.val;
            }
            root = root.left;
        }
        return 0;
    }
}

方法二: 递归反向中序遍历(从大到小排)

class Solution {
    int k;
    int ans = -1;
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        if(root == null){
            return ans;
        }

        inorderTraversal(root);
        return ans;

    }
    private void inorderTraversal(TreeNode root){
        if(root == null){
            return;
        }
        inorderTraversal(root.right);
        if(--k == 0){
            ans = root.val;
            return;
        }
        inorderTraversal(root.left);
    }
}
  1. 剑指 Offer 37. 序列化二叉树 - 力扣(LeetCode)

方法一: BFS

 /**
 * BFS(层序遍历)
 */
public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if(root == null){
            return "";
        }
        StringBuilder res = new StringBuilder();
        res.append("[");

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            if (node != null){
                res.append(node.val);
                res.append(",");
                queue.offer(node.left);
                queue.offer(node.right);
            }else{
                res.append("null");
                res.append(",");
            }
        }
        res.deleteCharAt(res.length() -1);
        res.append("]");
        return res.toString();


    }
    
    public TreeNode deserialize(String data) {
        if (data.equals("")){
            return null;
        }
        String[] nodeList = data.substring(1, data.length() - 1).split(",");
        TreeNode root = new TreeNode(Integer.parseInt(nodeList[0]));
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int index = 1;
        while (!queue.isEmpty()){
            TreeNode tree = queue.poll();
            if (!nodeList[index].equals("null")){
                tree.left = new TreeNode(Integer.parseInt(nodeList[index]));
                queue.offer(tree.left);
            }
            index++;
            if (!nodeList[index].equals("null")){
                tree.right = new TreeNode(Integer.parseInt(nodeList[index]));
                queue.offer(tree.right);
            }
            index++;
        }
        return root;
        
    }

}

2021年4月12日

  1. 剑指 Offer 26. 树的子结构 - 力扣(LeetCode)
class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(A == null || B == null){
            return false;
        }
     
        return help(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);

    }

    private boolean help(TreeNode tree1, TreeNode tree2){
        if(tree2 == null){
            return true;
        }
        if(tree1 == null || tree1.val != tree2.val){
            return false;
        }
        return help(tree1.left, tree2.left) && help(tree1.right, tree2.right);
    }
}
  1. 剑指 Offer 55 - I. 二叉树的深度 - 力扣(LeetCode)
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
    }
}

2021年4月13日

  1. Leetcode - 98. 验证二叉搜索树 - 力扣(LeetCode)

方法一: 迭代(中序遍历)

class Solution {
    
    public boolean isValidBST(TreeNode root) {
        long min = Long.MIN_VALUE;
        if(root == null){
            return true;
        }
        Deque<TreeNode> stack = new LinkedList<>();
        while(root != null || !stack.isEmpty()){
            while(root != null){
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            if(root.val <= min){
                return false;
            }
            min = root.val;
            root = root.right;
        }
       
        return true;
    }
}

方法二:递归(中序遍历)

class Solution {
    long min = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        if(root == null){
            return true;
        }
        if (!isValidBST(root.left)){
            return false;
        }
        if(root.val <= min){
            return false;
        }
        min = root.val;
        if (!isValidBST(root.right)){
            return false;
        }
        return true;
    }
}

方法三:递归

class Solution {
    public boolean isValidBST(TreeNode root) {
        return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }
    
    private boolean isValidBST(TreeNode node, long lowL, long upL){

        if (node == null) {
            return true;
        }

        if (node.val <= lowL || node.val >= upL) {
            return false;
        }
        return isValidBST(node.left, lowL, node.val) && isValidBST(node.right, node.val, upL);

    }
}
  1. Leetcode - 102. 二叉树的层序遍历 - 力扣(LeetCode)
class Solution {
    
    public List<List<Integer>> levelOrder(TreeNode root) {

        List<List<Integer>> res = new ArrayList<>();
        if(root == null){
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<TreeNode>(); 
        queue.offer(root);
        while(!queue.isEmpty()){
            List<Integer> list = new ArrayList<Integer>();
            int queueSize = queue.size();
            for(; queueSize>0; queueSize--){
                TreeNode node = queue.poll();
                list.add(node.val);
                if(node.left != null){
                    queue.offer(node.left);
                }
                if(node.right != null){
                    queue.offer(node.right);
                }
            }
            res.add(list);
        }
        return res;

    }
}

2021年4月14日份

  1. Leetcode - 623. 在二叉树中增加一行 - 力扣(LeetCode)

方法一: 层序遍历,维护队列保存上层节点

class Solution {
    public TreeNode addOneRow(TreeNode root, int val, int depth) {
        // 层序遍历
        if(depth == 1){
            return new TreeNode(val, root, null);
        }
        int level = 1;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);

        while(!queue.isEmpty() && level < depth -1){
            int size = queue.size();
            level++;
            for(; size > 0; size--){
                TreeNode node = queue.poll();
                if(node.left != null){
                    queue.offer(node.left);
                }
                if(node.right != null){
                    queue.offer(node.right);
                }
            }
        }
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            node.left = new TreeNode(val, node.left, null);
            node.right = new TreeNode(val, null, node.right);
        }

        return root;

    }
}
  1. Leetcode - 199. 二叉树的右视图 - 力扣(LeetCode)[腾讯题库]

方法一 : 层序遍历取每一层最右边的数

class Solution {

    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new ArrayList();
        // 层序遍历取每一层最右边的数
        if(root == null){
            return res;
        }
        List<List<Integer>> levelList = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            List<Integer> tmp = new ArrayList<>();
            int size = queue.size();
            for(; size > 0; size--){
                TreeNode node  = queue.poll();
                tmp.add(node.val);
                if(node.left != null){
                    queue.offer(node.left);
                }
                if(node.right != null){
                    queue.offer(node.right);
                }
            }
            levelList.add(new ArrayList(tmp));
        }

        for(List<Integer> list : levelList){
            res.add(list.get(list.size() - 1 ));
        }
        return res;
    }
}
  1. Leetcode - 863. 二叉树中所有距离为 K 的结点 - 力扣(LeetCode)[腾讯题库]

方法一: DFS(给每个节点添加上父节点) + BFS (层次遍历周围节点)

class Solution {

    Map<TreeNode, TreeNode> parentMap;
    Set<TreeNode> visited;
    List<Integer> res = new ArrayList<>();
    

    public List<Integer> distanceK(TreeNode root, TreeNode target, int K) {
        if(root == null){
            return res;
        }
        parentMap = new HashMap();
        addParent(null, root);
        visited = new HashSet<>();
        visited.add(target);
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(target);
        while (!queue.isEmpty() && K > 0) {
            int size = queue.size();
            K--;
            for (; size > 0; size--) {
                TreeNode node = queue.poll();
                visited.add(node);
                TreeNode parent = parentMap.get(node);

                if (parent != null && !visited.contains(parent)) {
                    queue.offer(parent);
                }
            
                if (node.left != null && !visited.contains(node.left)) {
                    queue.offer(node.left);
                }

                if (node.right != null && !visited.contains(node.right)) {
                    queue.offer(node.right);
                }
            }
        }

        while (!queue.isEmpty()) {
            res.add(queue.poll().val);
        }
        return res;

    }

    private void addParent(TreeNode parent, TreeNode node){
        if(node != null){
             parentMap.put(node, parent);
             addParent(node, node.left);
             addParent(node, node.right);
        }
    }
}

2021年4月15日份

  1. Leetcode - 108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)[腾讯题库]

方法一: 每次选取中间的节点作为根节点

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {

        return addNode(nums, 0, nums.length);

    }

    private TreeNode addNode(int[] nums, int left, int right){
        if(left >= right){
            return null;
        }
        int mid = left + right >> 1;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = addNode(nums, left, mid);
        root.right = addNode(nums, mid+1, right);
        return root;
    }
}
  1. Leetcode - 117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)[腾讯题库]

方法一: 迭代(层序遍历,每层左边节点next指向的该层右边节点,最后一个节点直接指向null)

class Solution {
    public Node connect(Node root) {
        if(root == null){
            return root;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        int sizeL;
        while(!queue.isEmpty()){
            sizeL = queue.size();
            for(; sizeL > 0; sizeL --){
                Node node = queue.poll();
                if(sizeL == 1){
                    node.next = null;
                }else{
                    node.next = queue.peek();
                }
                if(node.left != null){
                    queue.offer(node.left);
                }
                if(node.right != null){
                    queue.offer(node.right);
                }
            }
        }
        return root;
    }
}
  1. Leetcode - 116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)[和117进行比较]

方法二: 利用上层已经构建的next

class Solution {
    public Node connect(Node root) {
        if (root == null) {
            return root;
        }

        root.next = null;

        Node leftNode = root;

        while (leftNode.left != null) {

            Node head = leftNode;
            
            while (head != null) {
                head.left.next = head.right;
                if (head.next != null) {
                    head.right.next = head.next.left;
                }
                head = head.next;
            }
            
            leftNode = leftNode.left;
        }
        return root;
    }
}

2021年4月16日份

  1. Leetcode - 543. 二叉树的直径 - 力扣(LeetCode)[腾讯]

方法一:遍历获取每一个节点左右子树的最大深度,并且在遍历过程中维护更新最大直径

class Solution {
    int max = 0;
    public int diameterOfBinaryTree(TreeNode root) {
        if(root == null){
            return max;
        }
        help(root);
        return max;
    }

    // 遍历获取每一个节点左右子树的最大深度,并且在遍历过程中维护更新最大直径
    private int help(TreeNode node){
        if(node == null){
            return 0;
        }
        int leftDepth = help(node.left);
        int rightDepth = help(node.right);
        max = Math.max(max, leftDepth + rightDepth);
        return Math.max(leftDepth, rightDepth) + 1;

    }

}
  1. Leetcode - 429. N 叉树的层序遍历 - 力扣(LeetCode)[腾讯]

方法一: 同二叉树层序遍历(迭代)

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res = new ArrayList<>();
        if(root == null){
            return res;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        int sizeLeve;
        while(!queue.isEmpty()){
            sizeLeve = queue.size();
            List<Integer> nodeList = new  ArrayList<>(); 
            for(; sizeLeve > 0; sizeLeve--){
                Node node = queue.poll();
                nodeList.add(node.val);
                List<Node> children = node.children;
                for( Node child : children){
                    queue.offer(child);
                }
            }
            res.add(new ArrayList<Integer>(nodeList));
        }
        return res;  
    } Leetcode - Leetcode - Leetcode - 
}
  1. Leetcode - 95. 不同的二叉搜索树 II - 力扣(LeetCode)[腾讯]

方法: 遍历把每个数字作为根节点,生成左右的子树集合,再拼接左右子树

class Solution {
    public List<TreeNode> generateTrees(int n) {
        if(n == 0){
            return new LinkedList<TreeNode>();
        }
        return generateTrees(1, n);
    }
    private List<TreeNode> generateTrees(int l, int r){
        List<TreeNode> allTrees = new LinkedList<TreeNode>();
        if (l > r) {
            allTrees.add(null);
            return allTrees;
        }

        for(int i = l; i <= r; i++){
           List<TreeNode> leftNodes = generateTrees(l, i-1);
           List<TreeNode> rightNodes = generateTrees(i+1, r);
           // 遍历拼接左右节点
           for(TreeNode left : leftNodes){
               for(TreeNode right : rightNodes){
                   allTrees.add(new TreeNode(i, left, right));
               }
           }

        }
        return allTrees;

    }
}

2021年4月19日份

  1. Leetcode - 687. 最长同值路径 - 力扣(LeetCode)

方法:遍历获取每一个节点,就算左右子树最长同值路径,并且在遍历过程中维护更新整棵树的最大直径(类似题Leetcode543

class Solution {
    int max = 0;
    public int longestUnivaluePath(TreeNode root) {
        if(root == null){
            return max;
        }
        help(root);
        return max;
    }

    // 遍历获取每一个节点,就算左右子树最长同值路径,并且在遍历过程中维护更新整棵树的最大直径
    private int help(TreeNode node){
        if(node == null){
            return 0;
        }
        int left = help(node.left);
        int right = help(node.right);
        int leftMax = 0, rightMax = 0;
        if(node.left != null && node.left.val == node.val){
            leftMax = left + 1;
        }
        if(node.right != null && node.right.val == node.val){
            rightMax = right + 1;
        }
        max = Math.max(max, leftMax + rightMax);
        return Math.max(leftMax, rightMax);
    }

}
  1. Leetcode - 面试题 04.首个共同祖先 - 力扣(LeetCode)

方法一: 递归

class Solution {

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q){
            return root;
        }
        // 左右子树寻找p、q子树
        TreeNode left = lowestCommonAncestor(root.left, p, q); 
        TreeNode right = lowestCommonAncestor(root.left, p, q);
        // 左右子树各包含p、q返回该根节点
        if(left != null && right != null){
            return root;
        }
        // 全部在左边,返回作子树
        if(left != null && right == null){
            return left;
        }
        
        return right;
    }
}

方法二: 利用HashMap储存父节点

class Solution {
    Map<Integer, TreeNode> parent = new HashMap<Integer, TreeNode>();
    Set<Integer> visited = new HashSet<Integer>();

    public void addParent(TreeNode root) {
        if (root.left != null) {
            parent.put(root.left.val, root);
            addParent(root.left);
        }
        if (root.right != null) {
            parent.put(root.right.val, root);
            addParent(root.right);
        }
    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        addParent(root);
        while (p != null) {
            visited.add(p.val);
            p = parent.get(p.val);
        }
        while (q != null) {
            if (visited.contains(q.val)) {
                return q;
            }
            q = parent.get(q.val);
        }
        return null;
    }
}

2021年4月20日份

  1. Leetcode - 103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)

方法:层序遍历(在存储数据做处理)

class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if(root == null){
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean leftArrave = true;
        int levelSize;
        while(!queue.isEmpty()){
            levelSize = queue.size();
            Deque<Integer> levelList = new LinkedList<Integer>();
            for(; levelSize > 0; levelSize--){
                TreeNode node = queue.poll();
                if(leftArrave){
                    levelList.offerLast(node.val);
                }else{
                    levelList.offerFirst(node.val);
                }
                if(node.left != null){
                    queue.offer(node.left);
                }

                if(node.right != null){
                    queue.offer(node.right);
                }
            }
            leftArrave = !leftArrave;
            res.add(new ArrayList<Integer>(levelList));
        }
        return res;
    }
}
  1. Leetcode - 222. 完全二叉树的节点个数 - 力扣(LeetCode)
class Solution {
    public int countNodes(TreeNode root) {
        if(root == null){
           return 0;
        } 
        int left = countLevel(root.left);
        int right = countLevel(root.right);
        if(left == right){
            return countNodes(root.right) + (1<<left);
        }else{
            return countNodes(root.left) + (1<<right);
        }
    }
    private int countLevel(TreeNode root){
        int level = 0;
        while(root != null){
            level++;
            root = root.left;
        }
        return level;
    }
}

2021年4月21日份

  1. Leetcode - 530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)
class Solution {
    int min = Integer.MAX_VALUE;
    int pre = -100000000;
    public int getMinimumDifference(TreeNode root) {
        if(root == null){
            return min;
        }

        help(root);
        return min;
    }
    private void help(TreeNode root){
        if(root == null){
            return;
        }
        help(root.left);
        min = Math.min(min,root.val - pre);
        pre = root.val;
        help(root.right);
    }
}
  1. Leetcode - 剑指 Offer 34. 二叉树中和为某一值的路径 - 力扣(LeetCode)
class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        int sum = 0;
        def(root, targetSum);
        return res;
    }

    private void def(TreeNode root, int sum) {
        if(root == null){
            return;
        }

        path.add(root.val);
        sum -= root.val;
        if(root.left == null && root.right == null && sum == 0){
            res.add(new ArrayList<Integer>(path));
        } 
        
        def(root.left, sum);
        def(root.right, sum);
        path.remove(path.size()-1);
    

    }
}

2021年4月22日份

  1. Leetcode - 958. 二叉树的完全性检验 - 力扣(LeetCode)

方法 : 层序遍历

class Solution {
    public boolean isCompleteTree(TreeNode root) {
        if(root == null){
            return true;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean falg = false;
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            if(node == null){
                falg = true;
                continue;
            }
            if(falg){
                return false;
            }
            queue.offer(node.left);
            queue.offer(node.right);
        }
        return true;
    }
Leetcode - Leetcode - Leetcode - Leetcode - }
  1. Leetcode - 513. 找树左下角的值 - 力扣(LeetCode)

方法一: 从右到左的层序遍历

class Solution {
    int res;
    public int findBottomLeftValue(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            res = node.val;
            if(node.right != null){
                queue.offer(node.right);
            }
            if(node.left != null){
                queue.offer(node.left);
            }
        }
        return res;
    }
}

2021年4月23日份

  1. Leetcode - 563. 二叉树的坡度 - 力扣(LeetCode)

方法一: 双重递归

class Solution {

    public int findTilt(TreeNode root) {
        if(root == null){
            return 0;
        }
        int podu = Math.abs(getTreeNodeSum(root.left) - getTreeNodeSum(root.right));
        return podu + findTilt(root.left) + findTilt(root.right);

    }

    private int getTreeNodeSum(TreeNode root){
        if(root == null){
            return 0;
        }
        return root.val + getTreeNodeSum(root.left) + getTreeNodeSum(root.right);
    }

}

方法二: dfs更新总结点坡度

class Solution {

    int poduSum = 0;
    public int findTilt(TreeNode root) {
        dfs(root);
        return poduSum;

    }

    private int dfs(TreeNode root){
        if(root == null){
            return 0;
        }
        int left =  dfs(root.left);
        int right = dfs(root.right);
        poduSum += Math.abs(left - right);
        return left + right + root.val;
    }

}
  1. Leetcode - 653. 两数之和 IV - 输入 BST - 力扣(LeetCode)

方法一: 中序遍历 + 双指针

class Solution {
    List<Integer> list;
    public boolean findTarget(TreeNode root, int k) {
        if(root == null){
            return false;
        }
        list = new ArrayList<>();
        inorderTraversal(root);
        int l = 0;
        int r = list.size() - 1;
        int tmp;
        while(l < r){
            tmp = list.get(l) + list.get(r);
            if(tmp == k){
                return true;
            }
            if(tmp < k){
                l++;
            }else{
                r--;
            }
        }
        return false;
    }


    private void inorderTraversal(TreeNode root){
        if(root == null){
            return;
        }
        inorderTraversal(root.left);
        list.add(root.val);
        inorderTraversal(root.right);
    }
}

方法二: HashSet + 任意遍历

class Solution {
    Set < Integer > set = new HashSet();
    public boolean findTarget(TreeNode root, int k) {
        if(root == null){
            return false;
        }
        if(set.contains(k - root.val)){
            return true;
        }
        set.add(root.val);
        if(findTarget(root.left, k)){
            return true;
        }
        if(findTarget(root.right, k)){
            return true;
        }
        return false;
    }
}
  1. Leetcode - 617. 合并二叉树 - 力扣(LeetCode)

方法: 简单递归即可

class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if(root1 == null){
            return root2;
        }
        if(root2 == null){
            return root1;
        }
        root1.left = mergeTrees(root1.left, root2.left);
        root1.right = mergeTrees(root1.right, root2.right);
        root1.val += root2.val;

        return root1;

    }
}
  1. Leetcode - 606. 根据二叉树创建字符串 - 力扣(LeetCode)
class Solution {
    public String tree2str(TreeNode t) {
        if(t==null)
            return "";
        if(t.left==null && t.right==null)
            return t.val+"";
        if(t.right==null)
            return t.val+"("+tree2str(t.left)+")";
        return t.val+"("+tree2str(t.left)+")("+tree2str(t.right)+")";  
    }
}
posted @ 2021-04-28 16:16  Fate_p  阅读(64)  评论(0编辑  收藏  举报