练习一 : 汉诺塔
面试题 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 下标的
练习二 : 合并两个有序链表
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;
}
}
}
练习三 : 两两交换链表中的节点

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))

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