跳到内容

元数据卡

  • 前置知识:方法(第5章)、递归(第5章)
  • 预计时间:30 分钟
  • 阅读模式: 动手实践
  • 完成标志:能独立写出方法和递归代码,通过所有验收标准

这一章没有新知识。把你前几节学到的方法和递归用起来。先热身,再挑战,最后找 bug。

热身(5 分钟,必做)

1. 奇偶判断

写一个方法 isEven(int n),返回 true 如果 n 是偶数。在 main 里循环打印 1 到 10 的奇偶判断。

2. 三个数的最大值

写一个方法 max(int a, int b, int c) 返回三个数中最大的。

3. 重载问候

重载 greet 方法:greet(String name)greet(String name, String title),输出不同的问候语。

4. 递归阶乘

用递归写一个方法 int pow(int base, int exp),计算 base^exp。比如 pow(2, 5) = 32

5. 各位数字之和

用递归写 int sumDigits(int n),计算各位数字之和。比如 sumDigits(123) = 1+2+3 = 6

6. 倒计时

用递归写 void countdown(int n),倒计时输出 n, n-1, ..., 1, 0, 发射!

挑战(30 分钟,选做)

1. 老陈牌计算器

写一个程序,定义 addsubmuldiv 四个方法,从 main 传入两个数,输出四则运算结果。

java
// 预期输出示例
add(10, 5) = 15
sub(10, 5) = 5
mul(10, 5) = 50
div(10, 5) = 2

2. 二分搜索(递归版)

给定已排序数组 {1, 3, 5, 7, 9, 11, 13, 15},用递归实现二分查找,返回目标值的索引。如果没找到返回 -1

3. 文件搜索器

写一个程序,递归遍历整个项目目录,找到所有文件名包含关键词的文件(比如包含 "loop".java 文件)。打印出它们的完整路径。

4. 斐波那契性能测试

写一个 Benchmark 程序,分别测试普通递归版、记忆化递归版、循环版计算 F(40) 的时间。

F(40) = 102334155
普通递归: 1234ms
记忆化递归: 0ms
循环: 0ms

排障(找 Bug)

1. 交换失败

下面这个程序试图交换两个变量,但没有成功。解释为什么,并修复它:

java
public class Swap {
    public static void main(String[] args) {
        int a = 5, b = 10;
        swap(a, b);
        System.out.println("a=" + a + " b=" + b);  // 期望 a=10, b=5
    }

    static void swap(int x, int y) {
        int temp = x;
        x = y;
        y = temp;
    }
}

提示:值传递。swap 方法的修改只在它的栈帧里生效。考虑用数组或者在 main 里直接交换。

2. 回文判断

这段代码试图判断"一个字符串是不是回文",但有问题:

java
public class Palindrome {
    public static boolean isPalindrome(String s) {
        if (s.length() <= 1) return true;
        if (s.charAt(0) != s.charAt(s.length() - 1)) return false;
        return isPalindrome(s.substring(0, s.length() - 1));  // 找 bug 在这里
    }

    public static void main(String[] args) {
        System.out.println(isPalindrome("racecar"));  // 期望 true
        System.out.println(isPalindrome("hello"));    // 期望 false
        System.out.println(isPalindrome("a"));        // 期望 true
    }
}

提示:递归子调用减少了字符串吗?减少了哪一头?回文的定义是"从两边往里比较",你只砍了一头,会无限循环吗?

观察实验

栈溢出临界点

写一个递归程序(比如计算 1 到 n 的累加),在不同 n 值下运行,观察报 StackOverflowError 的临界点。尝试用以下命令调小栈空间:

bash
java -Xss256k Sum

看看栈空间从默认值缩减到 256KB 时,临界 n 值从多少降到多少。

验收标准

  • [ ] 你能写出带参数和返回值的方法
  • [ ] 你知道 void 表示不返回
  • [ ] 你能解释"值传递"——为什么 swap(a, b) 无法在方法内部交换外部变量
  • [ ] 你能画出 A→B→C 嵌套调用的调用栈变化
  • [ ] 你能解释方法重载的规则(同名、不同参数列表)
  • [ ] 你能手写一个简单的递归函数(阶乘、求和)
  • [ ] 你能正确解释"基准情况"和"递归情况"的关系
  • [ ] 你能画出 factorialRecur(4) 的调用栈变化过程
  • [ ] 你知道什么情况下递归会栈溢出

旅人笔记

跑步要跑,代码要写。学编程只有一条路:动手写。 先做热身再挑战,遇到 bug 别急——画调用栈、加打印、一步步缩小范围。你和老陈的距离,只是练习的遍数。

下一站:数组

从单兵作战到拆解任务,你已经掌握了一个程序的基本结构——变量、条件、循环、方法和递归。但你要处理的数据越来越多了。一个人的剑谱要记,十个人的呢?一百个人的呢?下一章,我们打开数组的门——它用数字下标就能让你走遍整个数据集合。

Built with VitePress | Software Systems Atlas