【树-中等】剑指 Offer II 047. 二叉树剪枝

给定一个二叉树,其中每个节点的值为0或1,该算法通过深度优先搜索(DFS)遍历树,删除所有只包含0的子树。当一个节点的所有子节点都被删除时,若该节点值也为0,则删除该节点。代码中定义了一个`dfs`函数用于递归处理,并在`pruneTree`函数中检查并处理根节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目
给定一个二叉树 根节点 root ,树的每个节点的值要么是 0,要么是 1。请剪除该二叉树中所有节点的值为 0 的子树。

节点 node 的子树为 node 本身,以及所有 node 的后代。

示例 1:

输入: [1,null,0,0,1]
输出: [1,null,0,null,1]
解释:
只有红色节点满足条件“所有不包含 1 的子树”。
右图为返回的答案。

示例 2:

输入: [1,0,1,0,0,0,1]
输出: [1,null,1,null,1]
解释:
示例 3:

输入: [1,1,0,1,1,0,1,0]
输出: [1,1,0,1,1,null,1]
解释:

提示:

二叉树的节点个数的范围是 [1,200]
二叉树节点的值只会是 0 或 1

注意:本题与主站 814 题相同
【代码】
在这里插入图片描述

class Solution:
    def dfs(self,root):
        if not root:
            return 0
        L=self.dfs(root.left)
        R=self.dfs(root.right)
        if L==0:
            root.left=None
        if R==0:
            root.right=None
        return root.val+L+R
        
    def pruneTree(self, root: TreeNode) -> TreeNode:
        rs=self.dfs(root)
        if root.val==0 and (not root.left and not root.right):
            return None
        return root
<think>好的,我现在需要处理用户关于Java算法综合性问题的问题。用户希望得到综合性的Java算法面试题或练习题的前十名,并且要求结合站内引用内容。首先,我需要回顾用户提供的引用内容,看看是否有相关信息可以利用。 引用[1]提到面试流程包括算法题,通常为LeetCode高频题或剑指offer高频题。引用[2]列出了高频问题场景,如数组/链表操作、动态规划、哈希表、双指针、二叉树遍历,还提到时间复杂度优化和边界条件处理的重要性。引用[3]则涉及空间复杂度分析和哈希表的使用。 接下来,我需要结合这些信息,确定Java算法中的Top 10题目。通常来说,高频题目包括两数之和、反转链表、二叉树遍历、动态规划问题如爬楼梯、最长子序列、合并有序数组、括号生成、链表环检测、数组中的重复元素以及堆栈实现队列等。这些题目覆盖了引用中提到的主要场景和考察重点。 需要确保每个问题都符合用户的要求,并且引用相关的知识点。例如,两数之和可以使用哈希表优化,二叉树遍历涉及递归和迭代,动态规划问题需要时间复杂度优化等。同时,每个问题的解析应包含核心思路、时间复杂度和空间复杂度,以及可能的优化方法,如引用[3]提到的哈希表方法。 还要注意回答结构清晰,分点列出每个问题,确保语言简洁,符合中文回答的要求。最后,生成的相关问题需要围绕这些题目类型和考察点展开,帮助用户进一步深入学习。</think>### Java算法综合性问题Top 10(面试/练习) --- #### 1. **两数之和(Two Sum)** **问题**:给定整数数组和目标和,返回两数下标使它们的和等于目标。 **核心**:哈希表(HashMap)实现$O(n)$时间复杂度[^3]。 **代码关键**: ```java public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] { map.get(complement), i }; } map.put(nums[i], i); } return new int[0]; } ``` --- #### 2. **反转链表(Reverse Linked List)** **问题**:单链表反转(迭代或递归)。 **考察点**:指针操作与边界条件处理[^2]。 **迭代法**: ```java public ListNode reverseList(ListNode head) { ListNode prev = null, curr = head; while (curr != null) { ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev; } ``` --- #### 3. **二叉树的中序遍历(Inorder Traversal)** **问题**:输出二叉树中序遍历结果(递归与非递归)。 **考察点**:栈的应用与递归转迭代的能力[^2]。 **非递归实现**: ```java public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); TreeNode curr = root; while (curr != null || !stack.isEmpty()) { while (curr != null) { stack.push(curr); curr = curr.left; } curr = stack.pop(); res.add(curr.val); curr = curr.right; } return res; } ``` --- #### 4. **爬楼梯(Climbing Stairs)** **问题**:每次爬1或2阶,求到达第$n$阶的方法数。 **动态规划**:状态转移方程$f(n) = f(n-1) + f(n-2)$,空间复杂度优化为$O(1)$。 ```java public int climbStairs(int n) { if (n <= 2) return n; int a = 1, b = 2; for (int i = 3; i <= n; i++) { int c = a + b; a = b; b = c; } return b; } ``` --- #### 5. **最长递增子序列(Longest Increasing Subsequence)** **问题**:求数组中最长递增子序列的长度。 **优化方法**:贪心+二分法,时间复杂度$O(n \log n)$。 **代码片段**: ```java public int lengthOfLIS(int[] nums) { int[] tails = new int[nums.length]; int len = 0; for (int num : nums) { int i = Arrays.binarySearch(tails, 0, len, num); if (i < 0) i = -(i + 1); tails[i] = num; if (i == len) len++; } return len; } ``` --- #### 6. **合并两个有序数组(Merge Sorted Array)** **问题**:将两个有序数组合并到第一个数组中。 **双指针技巧**:从后向前遍历避免覆盖原数据。 ```java public void merge(int[] nums1, int m, int[] nums2, int n) { int i = m - 1, j = n - 1, k = m + n - 1; while (j >= 0) { nums1[k--] = (i >= 0 && nums1[i] > nums2[j]) ? nums1[i--] : nums2[j--]; } } ``` --- #### 7. **括号生成(Generate Parentheses)** **问题**:生成所有有效的$n$对括号组合。 **回溯法**:剪枝条件控制左右括号数量平衡[^2]。 ```java public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<>(); backtrack(res, "", 0, 0, n); return res; } private void backtrack(List<String> res, String s, int left, int right, int n) { if (s.length() == 2 * n) { res.add(s); return; } if (left < n) backtrack(res, s + "(", left + 1, right, n); if (right < left) backtrack(res, s + ")", left, right + 1, n); } ``` --- #### 8. **环形链表检测(Linked List Cycle)** **问题**:判断链表中是否存在环。 **快慢指针法**:Floyd判圈算法,时间复杂度$O(n)$。 ```java public boolean hasCycle(ListNode head) { ListNode slow = head, fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) return true; } return false; } ``` --- #### 9. **数组中重复的数字(Find Duplicate Number)** **问题**:数组包含$n+1$个$[1, n]$的数,找到重复数。 **原地哈希法**:利用数与下标映射关系。 ```java public int findDuplicate(int[] nums) { while (true) { int num = nums[0]; if (nums[num] == num) return num; nums[0] = nums[num]; nums[num] = num; } } ``` --- #### 10. **用栈实现队列(Implement Queue using Stacks)** **问题**:用两个栈模拟队列的先进先出特性。 **双栈反转法**:输入栈与输出栈配合,均摊时间复杂度$O(1)$[^2]。 ```java class MyQueue { Stack<Integer> in = new Stack<>(); Stack<Integer> out = new Stack<>(); public void push(int x) { in.push(x); } public int pop() { if (out.isEmpty()) { while (!in.isEmpty()) out.push(in.pop()); } return out.pop(); } } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值