[Java算法] 递归(1)

练习一 : 汉诺塔

面试题 08.06. 汉诺塔问题 - 力扣(LeetCode)

java 复制代码
class Solution {
    public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
        dfs(A,B,C,A.size());
    }
        public void dfs(List<Integer> from, List<Integer> tmp, List<Integer> to, int n) {
        // 递归终止条件:只有1个圆盘,直接移动
        if (n == 1) {
            // 修正:remove(-1) → 移除列表最后一个元素(模拟栈顶,符合汉诺塔"从上到下取圆盘")
            to.add(from.remove(from.size() - 1));
            return;
        }

        // 步骤1:把n-1个圆盘从from移到tmp(以to为辅助)
        dfs(from, to, tmp, n - 1);
        // 步骤2:把第n个圆盘(最大的)从from移到to
        to.add(from.remove(from.size() - 1));
        // 步骤3:把n-1个圆盘从tmp移到to(以from为辅助)
        dfs(tmp, from, to, n - 1);
    }
}

细节问题 :

每次转移的圆盘应该是最上面的(A.size()-1)最小的哪个 , 而不是转移 0 下标的

练习二 : 合并两个有序链表

21. 合并两个有序链表 - 力扣(LeetCode)

java 复制代码
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null){
            return l2;
        }
        if(l2 == null){
            return l1;
        }
        if(l1.val<=l2.val){
            
            l1.next = mergeTwoLists(l1.next,l2);
           
            return l1;
        }else{
           
            l2.next = mergeTwoLists(l1,l2.next);
            
            return l2;
        }
        
    }
}

练习三 : 两两交换链表中的节点

24. 两两交换链表中的节点 - 力扣(LeetCode)

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
public ListNode swapPairs(ListNode head) {
    // 递归终止条件:空节点 或 只剩一个节点,无法交换,直接返回
    if(head == null || head.next == null){
        return head;
    }

    // 递归处理:从第三个节点开始,后面的所有节点先两两交换
    ListNode tmp = swapPairs(head.next.next);

    // 现在交换前两个节点:
    ListNode ret = head.next;   // 新头 = 原来的第二个节点
    ret.next = head;            // 第二个节点指向第一个节点(完成交换)
    head.next = tmp;            // 第一个节点指向后面已经交换好的部分

 
    return ret; // 返回新的头节点
}
}

算法原理 : 深度优先遍历(递归)

宏观角度看待 : 认为这个函数一定能完成排序工作

  • tmp = 后面全部换好的头
  • ret = 当前两个里的新头(第二个节点)
  • 换向 + 接尾巴
  • 必须 return 新头 ret,上层才能正常拼接

练习四 : 快速幂(Pow(x,n))

50. Pow(x, n) - 力扣(LeetCode)

java 复制代码
class Solution {
    public double myPow(double x, int n) {
        if((x-1) == 0){
            return 1;
        }
        if(n == -2147483648){  // 单独处理最小值
            n++;               // 先+1,变成 -2147483647(不会溢出)
            double res = 1.0 / pow(x, -n);
            return res / x;    // 再除一次x,补回刚才+1
        }
        if(n == 1){
            return x;
        }if(n<0){
            return 1.0/pow(x,(-1)*n);
        }
        if(n == 0){
            return 1.0;
        }
        if(n>0){
            return pow(x,n);
        }

        return 1;
    }
    public double pow(double x, int n){
        if(n == 1){
            return x;
        }
        double tmp = pow(x,n/2);
        return n%2 == 0?tmp*tmp:tmp*tmp*x;
    }
}

处理整型越界情况

当 -2147483648 去掉符号 2147483648 会超出 整型 2147483647 ; 我们就按 2147483647 次处理 , 最后再单独处理一次即可

实际代码完全不会报错,直接大胆传原负数 n 就行;最终结果靠底层两层递归兜底算出:n = 0 直接返回 1,n = -1 算出 1×1×X;再顺着递归一层层回溯相乘,最后外层统一用倒数规整负幂,全程避开数值越界

java 复制代码
class Solution 
{
 public double myPow(double x, int n) 
 {
 return n < 0 ? 1.0 / pow(x, n) : pow(x, n);
 }
 public double pow(double x, int n)
 {
 if(n == 0) return 1.0;
 double tmp = pow(x, n / 2);
 return n % 2 == 0 ? tmp * tmp : tmp * tmp * x;
 }
}

练习五 : 计算布尔二叉树的值

2331. 计算布尔二叉树的值 - 力扣(LeetCode)

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean evaluateTree(TreeNode root) {
        if(root.left == null){
            return root.val ==1?true:false;
        }
        boolean left = evaluateTree(root.left);
        boolean right = evaluateTree(root.right);
        return root.val == 2?(left||right):(left&&right);
    }
}

练习六 : 求根节点到叶子节点数组之和

129. 求根节点到叶节点数字之和 - 力扣(LeetCode)

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int count = 0;  // 全局变量,记录最终总和

    public int sumNumbers(TreeNode root) {
        if (root == null) return 0; // 增加空树判断,更健壮
        dfs(root, 0);  // 从 0 开始更标准
        return count;
    }

    // DFS 递归:prev 表示当前路径已拼接的数字
    public void dfs(TreeNode root, int prev) {
        // 路径拼接公式
        int num = prev * 10 + root.val;

        // 到达叶子节点,累加结果
        if (root.left == null && root.right == null) {
            count += num;
            return;
        }

        // 递归左右子树
        if (root.left != null)  dfs(root.left, num);
        if (root.right != null) dfs(root.right, num);
    }
}
相关推荐
Henray202415 小时前
最低公共祖先 LCA
java·面试
shehuiyuelaiyuehao15 小时前
关于进程和线程的关系
java·开发语言
河阿里15 小时前
SpringBoot:项目启动速度深度优化
java·spring boot·后端
AaronCos15 小时前
弄懂java泛型中的extends和super
java·开发语言
用户2395261801015 小时前
别再 new 满天飞了!一文搞懂工厂模式,程序员终于不用手搓对象了 😆
java
阿丰资源15 小时前
基于SpringBoot的企业客户管理系统(附源码)
java·spring boot·后端
yongui4783415 小时前
基于 GA 优化的 BP 神经网络算法分析与 MATLAB 实现
神经网络·算法·matlab
两年半的个人练习生^_^16 小时前
SpringBoot 项目使用 Jasypt 实现配置文件敏感信息加密
java·spring boot·后端
JAVA学习通16 小时前
开云集致 Java开发 实习 一面
java·开发语言
阿旭超级学得完16 小时前
C++11(初始化)
java·开发语言·数据结构·c++·算法