zoukankan      html  css  js  c++  java
  • 刷题笔记-树

    刷题笔记-树

    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)+")";  
        }
    }
    
  • 相关阅读:
    [HNOI2019]JOJO
    [TJOI2019]唱、跳、rap和篮球
    [ZJOI2019]开关
    jzoj5746
    [JSOI2019]神经网络(指数生成函数)
    [TJOI2019]甲苯先生的线段树
    [JSOI2019]节日庆典
    XSY1519
    XSY1528
    springboot actuator监控笔记
  • 原文地址:https://www.cnblogs.com/fate-pc/p/14714618.html
Copyright © 2011-2022 走看看