Skip to content

本页系统梳理 Java/ 目录下的 LeetCode 题解工程体系。你将了解每道题的目录如何组织、代码文件之间的调用关系、以及如何利用已有的解题模板快速上手新题目。无论你是第一次打开本仓库,还是想参照已有代码规范提交新解法,这里都是你的起点。

目录结构总览

Java 题解区采用按题目独立建目录的方式组织,每个题目目录是一个自包含的微型工程。目录名使用中文题名,部分题目在名称末尾追加 LeetCode 题号(如 P1P198)以便快速检索。整体结构如下图所示:

Java/
├── 两数之和P1/          ← 带题号的标准结构
│   ├── README.md
│   └── src/
│       ├── main/
│       │   └── Solution.java
│       └── test/
│           └── Test.java
├── 接雨水/              ← 不带题号的标准结构
│   ├── README.md
│   └── src/
│       ├── main/
│       │   └── Solution.java
│       └── test/
│           └── test.java
├── 二叉树/              ← 特殊结构:数据结构专题,无 src 分层
│   ├── BinaryTree.java
│   ├── BinaryTree.md
│   └── TreeNode.java
└── ...                  ← 共 35 个题目目录

Sources: 两数之和P1/src/main/Solution.java, 接雨水/src/test/test.java, 二叉树/TreeNode.java

标准题目目录模型

绝大多数题目目录遵循同一套三层分离结构。下面的 Mermaid 图展示了各文件之间的依赖与调用关系——先读 README 了解题意,再阅读 Solution 中的核心算法,最后通过 Test 验证输出。

前提说明:下图使用 Mermaid 语法绘制。箭头方向表示"调用/依赖"关系,即 Test 依赖 Solution,README 独立存在提供题面信息。

mermaid
graph TD
    A["README.md<br/>题面 & 链接"] --> B["src/main/Solution.java<br/>核心解题类"]
    B --> C["src/test/Test.java<br/>本地测试入口"]
    C -->|"import 导入"| B
    D["package 声明<br/>中文包名 = 目录路径"] -.-> B
    D -.-> C

三层文件职责

层级文件职责示例
文档层README.md记录题目标题、LeetCode 链接,部分包含完整题面[地址](https://leetcode.cn/problems/...)
核心层src/main/Solution.java实现题解逻辑,方法签名与 LeetCode 保持一致public int[] twoSum(int[] nums, int target)
验证层src/test/Test.java构造测试用例,main 方法中实例化 Solution 并打印结果System.out.println(Arrays.toString(solution.twoSum(...)))

Sources: 两数之和P1/README.md, 两数之和P1/src/main/Solution.java, 两数之和P1/src/test/Test.java

包命名与导入约定

本项目的一个显著特征是使用中文目录名作为 Java 包名。包声明严格镜像目录路径,这保证了每个题目的 Solution 类可以在 Test 类中被正确导入。

包声明规则package <目录名>.src.main;,目录名含中文和题号时原样保留。

java
// 目录: Java/两数之和P1/src/main/Solution.java
package 两数之和P1.src.main;

public class Solution {
    public int[] twoSum(int[] nums, int target) { ... }
}

测试文件导入规则import <目录名>.src.main.Solution;,与包声明一一对应。

java
// 目录: Java/两数之和P1/src/test/Test.java
package 两数之和P1.src.test;

import 两数之和P1.src.main.Solution;

public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(Arrays.toString(solution.twoSum(new int[]{2, 7, 11, 15}, 9)));
    }
}

这一约定的优势在于:每个题目目录天然形成独立的 Java 包命名空间,即使不同题目都有名为 Solution 的类,也不会产生冲突。但需要注意,编译时需确保类路径(classpath)正确指向 Java/ 根目录。

Sources: 两数之和P1/src/main/Solution.java, 两数之和P1/src/test/Test.java, 打家劫舍P198/src/test/Test.java

解题代码模板详解

标准模板:Solution 类

Solution 类是解题的核心载体,其方法签名严格遵循 LeetCode 的 OJ 接口要求。下面以一个完整的动态规划题目为例,展示模板的关键组成:

java
package 打家劫舍P198.src.main;        // ① 包声明:镜像目录路径

public class Solution {                // ② 类名:统一为 Solution
    public int rob(int[] nums) {        // ③ 方法签名:与 LeetCode 一致
        if (nums.length == 0) {return 0;}
        if (nums.length == 1 && nums[0]==0) {return 0;}
        if (nums.length == 1) {return nums[0];}
        if (nums.length == 2) {return Math.max(nums[0], nums[1]);}
        int[] dp = new int[nums.length]; // ④ 核心算法逻辑
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for (int i = 2; i < nums.length; i++) {
            dp[i] = Math.max(dp[i-2] + nums[i], dp[i-1]);
        }
        return dp[nums.length-1];        // ⑤ 返回结果
    }
}

模板要点归纳:

要素规范说明
包声明package <中文目录名>.src.main;必须与物理目录路径完全一致
类名Solution(默认)设计类题目可能使用其他名称(如 RandomizedSet
方法签名与 LeetCode 题面完全一致保证代码可直接粘贴至 OJ 提交
注释中文注释说明核心思路部分代码含英文注释或两种语言混合
备选解法以注释形式保留在源码中如验证回文串的旧版双指针解法

Sources: 打家劫舍P198/src/main/Solution.java, 插入删除和获取随机元素/src/main/RandomizedSet.java, 验证回文串/src/main/Solution.java

测试模板:Test 类

Test 类承担本地验证的职责,通过 main 方法手动构造测试用例并打印输出。模板固定、编写成本低:

java
package 打家劫舍P198.src.test;          // 包声明

import 打家劫舍P198.src.main.Solution;  // 导入被测类

public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();            // 实例化
        System.out.println(solution.rob(new int[]{1,2,3,1}));    // 测试用例1
        System.out.println(solution.rob(new int[]{2,7,9,3,1}));  // 测试用例2
    }
}

Sources: 打家劫舍P198/src/test/Test.java

特殊结构:语言特性探索文件

部分题目的 src/test/ 目录下包含多个测试文件,它们不仅验证题解,还用于探索 Java 语言特性。这些文件以被探索的 API 或语法命名,是理解代码中特定用法的重要参考。

题目目录测试文件探索的语言特性
验证回文串testcharAt.javaString.charAt() 索引访问
验证回文串testisLetterOrDigit.javaCharacter.isLetterOrDigit() 字符分类
验证回文串testLength.java字符串长度相关 API
赎金信toCharArray.javaString.toCharArray() 字符数组转换
赎金信for语法糖.java增强 for 循环语法

toCharArray.java 为例,它独立演示了如何将字符串转为字符数组并遍历——这正是 赎金信 题解中 for (char c : magazine.toCharArray()) 的底层机制:

java
package 赎金信.src.test;

public class toCharArray {
    public static void main(String[] args) {
        String str = "hello world";
        char[] chars = str.toCharArray();
        for (char aChar : chars) {
            System.out.println(aChar);
        }
    }
}

当你阅读题解代码时遇到不熟悉的 Java API,可以先在同目录的测试文件中找到它的最小可运行示例,理解行为后再回到主逻辑。

Sources: 赎金信/src/test/toCharArray.java, 验证回文串/src/test/testisLetterOrDigit.java, 验证回文串/src/test/testcharAt.java

特殊结构:数据结构专题(二叉树)

二叉树 目录与标准题目目录的结构不同,它没有 src/main/test 分层,而是将所有文件平铺在根目录下。这是因为二叉树作为通用数据结构,其节点定义和操作方法需要被多个题目复用,而非服务于单一 LeetCode 题目。

二叉树/
├── BinaryTree.java    ← 树的操作类:插入、前/中/后序遍历
├── BinaryTree.md      ← 完整的中文文档:概念、类型、遍历、应用
└── TreeNode.java      ← 节点定义:value、left、right

TreeNode.java 定义了最基础的二叉树节点结构,这是所有树形题目的基石:

java
package 二叉树;

class TreeNode {
    int value;
    TreeNode left;
    TreeNode right;

    TreeNode(int value) {
        this.value = value;
        left = null;
        right = null;
    }
}

BinaryTree.java 则封装了基于此节点的插入与三种遍历操作。当你在其他链表或树形题目中需要使用二叉树结构时,可以直接引用这套定义。如需深入了解二叉树的遍历与平衡性判断,推荐阅读 二叉树:遍历、插入与平衡性判断

Sources: 二叉树/TreeNode.java, 二叉树/BinaryTree.java, 二叉树/BinaryTree.md

特殊结构:设计类题目

LeetCode 中的设计类题目(如 O(1) 时间插入、删除和获取随机元素)要求实现一个特定名称的类,而非标准的 Solution 类。本项目对此的处理方式是:将主文件命名为 LeetCode 要求的类名。

java
// 文件: 插入删除和获取随机元素/src/main/RandomizedSet.java
package 插入删除和获取随机元素.src.main;

public class RandomizedSet {
    public RandomizedSet() { ... }
    public boolean insert(int val) { ... }
    public boolean remove(int val) { ... }
    public void getRandom() { ... }
}

文件末尾保留了 LeetCode 的使用说明注释,指明了实例化与调用方式,这是从 OJ 模板直接拷贝的规范格式。

Sources: 插入删除和获取随机元素/src/main/RandomizedSet.java, 插入删除和获取随机元素/src/test/Test.java

题目分类与完成状态

当前 Java/ 目录共包含 35 个题目目录,覆盖了 LeetCode 经典面试题目的多种算法范式。下表按算法思想分类整理,并标注每道题的完成状态——"已完成"表示 Solution 中包含可运行的核心算法逻辑,"待完善"表示方法体为空或仅返回占位值。

动态规划

题目题号核心思路状态
爬楼梯P7070状态转移 dp[i] = dp[i-1] + dp[i-2]✅ 已完成
斐波那契数P509509变量滚动优化空间至 O(1)✅ 已完成
第N个泰波那契数P11371137三变量滚动✅ 已完成
打家劫舍P198198dp[i] = max(dp[i-2]+nums[i], dp[i-1])✅ 已完成
不同路径P6262二维 DP 初始化首行首列✅ 已完成
最小路径和P6464原地修改 grid 数组✅ 已完成
删除并获得点数P740740打家劫舍变体⏳ 待完善
使用最小花费爬楼梯P746746爬楼梯变体⏳ 待完善
不同路径IIP6363含障碍物的路径 DP⏳ 待完善

双指针与滑动窗口

题目题号核心思路状态
盛最多水的容器11左右指针向内收缩✅ 已完成(暴力法)
长度最小的子数组209滑动窗口左右指针✅ 已完成
找到字符串中所有字母异位词438固定窗口 + 字符计数✅ 已完成
无重复字符的最长子串P33滑动窗口⏳ 待完善

贪心策略

题目题号核心思路状态
买卖股票的最佳时机121遍历维护最小价格✅ 已完成
买卖股票的最佳时机2122所有正收益累加✅ 已完成
跳跃游戏55维护最远可达位置✅ 已完成
H指数274排序后线性扫描✅ 已完成
分发糖果135双向遍历⏳ 待完善

哈希表与字符串

题目题号核心思路状态
两数之和P11暴力双重循环✅ 已完成
赎金信38326 字母计数数组✅ 已完成
同构字符串205双向字符映射数组✅ 已完成
验证回文串125双指针 + isLetterOrDigit✅ 已完成
回文数P99✅ 已完成
整数反转P97✅ 已完成
罗马数字转整数13✅ 已完成
整数转罗马数字12✅ 已完成
最长公共前缀14✅ 已完成
找出字符串中第一个匹配项的下标28✅ 已完成
最小覆盖子串76✅ 已完成
三数之和15排序 + 双指针⏳ 待完善
单词规律290✅ 已完成

数组操作

题目题号核心思路状态
轮转数组189三次翻转法✅ 已完成
除自身以外数组的乘积238左右前缀积两遍扫描✅ 已完成
航班预订统计1109差分数组✅ 已完成
多数元素169✅ 已完成
最后一个单词的长度58✅ 已完成

链表与设计

题目题号核心思路状态
插入删除和获取随机元素380设计类 RandomizedSet⏳ 待完善
两数相加P22链表逐位相加⏳ 待完善

Sources: 爬楼梯P70/src/main/Solution.java, 长度最小的子数组/src/main/Solution.java, 跳跃游戏/src/main/Solution.java, 赎金信/src/main/Solution.java, 轮转数组/src/main/Solution.java, 除自身以外数组的乘积/src/main/Solution.java

编码风格与注释模式

通过逐一检视已完成的 Solution 文件,可以归纳出三种典型的注释风格:

风格一:行内中文注释——在关键算法步骤旁用中文说明意图,是最常见的模式。例如 赎金信 的字符计数逻辑:// 遍历magazine字符串,统计每个字符出现的次数赎金信/src/main/Solution.java

风格二:英文简短注释——用极简的英文标注核心变量或决策点。例如 跳跃游戏int maxPosition = 0; // record maxPoistion// good solution跳跃游戏/src/main/Solution.java

风格三:Javadoc + 备选解法注释——对方法提供完整的参数说明文档,并在源码中以注释形式保留备选或旧版解法。例如 长度最小的子数组 使用了 Javadoc 格式的 @param / @return 说明,并在文件尾部以注释保留了暴力解法;验证回文串 更是将整个旧版双指针实现以块注释形式保留。长度最小的子数组/src/main/Solution.java, 验证回文串/src/main/Solution.java

此外,部分题目在 Solution 类的 main 方法中以注释形式嵌入了测试代码(如 H指数轮转数组),这种做法将验证逻辑与核心逻辑放在同一文件中,方便快速调试但不符合标准模板的三层分离规范。

Sources: H指数/src/main/Solution.java, 轮转数组/src/main/Solution.java

多语言扩展

极少数题目目录的 src/main/ 下包含非 Java 的解法文件,作为跨语言参考:

题目目录附加文件语言
斐波那契数P509Solution.pySolution.cPython、C
三数之和Solution.pyPython

这些文件与 Solution.java 并列放置在同一目录下,命名遵循 <类名>.<扩展名> 的惯例。它们不是 Java 编译流程的一部分,仅供对照阅读不同语言的实现差异。如需系统了解 JavaScript/TypeScript 题解,请参阅 JavaScript / TypeScript 题解:编号检索与多种解法对比

Sources: 斐波那契数P509/src/main/Solution.java

README 文档规范

各题目的 README.md 目前存在两种深度的文档模式:

简洁模式(多数题目):仅包含题目标题和 LeetCode 链接,一行即可完成。

markdown
## 买卖股票的最佳时机2
[地址](https://leetcode.cn/problems/rotate-array/description/?envType=study-plan-v2&envId=top-interview-150)

详细模式(少数题目):包含完整的题目描述、示例输入输出和约束条件。例如 跳跃游戏 的 README 给出了完整的题面、两个示例及通义的分析思路;H指数 的 README 包含了 h 指数的维基百科定义和详细示例。这种模式对离线阅读和理解题意非常友好。

注意:当前部分 README 的标题与目录名不一致(如 打家劫舍P198/README.md 的标题写着"多数元素"),这是历史遗留问题,阅读时请以目录名为准。

Sources: 两数之和P1/README.md, 跳跃游戏/README.md, H指数/README.md

快速上手:新建一道 Java 题解

当你准备为一道新的 LeetCode 题目添加 Java 解法时,按照以下流程操作即可与现有工程保持一致:

mermaid
flowchart TD
    A["1. 在 Java/ 下新建目录<br/>格式: 中文题名P题号"] --> B["2. 创建 src/main/Solution.java<br/>声明包名 & LeetCode 方法签名"]
    B --> C["3. 创建 src/test/Test.java<br/>导入 Solution,编写 main 测试"]
    C --> D["4. 创建 README.md<br/>写入题目标题 & LeetCode 链接"]
    D --> E["5. 实现 Solution 中的算法逻辑"]
    E --> F["6. 运行 Test.main 验证输出"]
    F --> G{"输出正确?"}
    G -->|是| H["✅ 完成"]
    G -->|否| E

步骤一:创建目录。目录名建议使用中文题名 + 题号后缀(如 最长回文子串P5),便于在文件管理器中直观定位。

步骤二:编写 Solution.java。包声明必须与目录路径完全对应,方法签名照抄 LeetCode 题面:

java
package 最长回文子串P5.src.main;

public class Solution {
    public String longestPalindrome(String s) {
        // 在此实现你的解法
        return "";
    }
}

步骤三:编写 Test.java。导入 Solution 类,在 main 方法中构造至少两个测试用例:

java
package 最长回文子串P5.src.test;

import 最长回文子串P5.src.main.Solution;

public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.longestPalindrome("babad"));
        System.out.println(solution.longestPalindrome("cbbd"));
    }
}

步骤四:编写 README.md。至少包含题目标题和 LeetCode 链接,鼓励补充完整题面:

markdown
## 最长回文子串
[地址](https://leetcode.cn/problems/longest-palindromic-substring/)

步骤五至六:实现算法 → 运行验证 → 循环修正,直到测试用例输出与预期一致。

延伸阅读

本页聚焦于 Java 题解的工程结构与模板规范。要深入理解各类算法思想的实现细节,推荐按以下路径继续探索: