【递归算法】字母大小写全排列

文章摘要:

  • 本文解析LeetCode题目《字母大小写全排列》,要求生成给定字符串所有字母大小写组合。通过决策树模型展示递归过程:遍历字符串,遇到字母时分别添加大小写形式,数字则直接添加。使用回溯法维护全局变量ret(结果集)和path(当前路径),递归出口为遍历完字符串时保存结果。提供两种Java实现:版本一显式处理大小写转换,版本二封装转换函数。两种方案均通过回溯恢复现场确保状态正确,最终返回所有可能组合。

文章目录

题目链接

一、题目解析

题目会给出一个字符串,让我们将字符串里的字母转换大小写,找出所有的组合。

例如示例 1 给出的字符串 s = "a1b2",我们需要返回 "a1b2", "a1B2", "A1b2", "A1B2"

二、算法原理 + 代码实现

决策树

我们按照暴搜的普遍思路:依次枚举画出决策树。

根据示例 1:

从左往右遍历字符串,遇到字母就选择添加大写还是小写,遇到数字就直接添加,枚举每一种情况。

决策树如下:

全局变量

这里依然是两个全局变量:ret 记录结果、path 记录路径。

dfs 函数

函数头

由于我们是遍历字符串,要将 s 作为参数,而且是通过递归遍历的,因此需要知道下标 pos。

Java 复制代码
dfs(String s, int pos);

函数体

考虑每一次递归所做的事情,那就是遇到字母就考虑大小写,而遇到数字就无需考虑直接添加。

Java 复制代码
if (字母的判定条件) {
	// 先添加小写
	// 再添加大写
} else {
	// 添加数字
}

注意,每一次添加完递归回来后都要考虑恢复现场。

除了依次添加大小写,也可以直接通过一个函数完成大小写的转换:

Java 复制代码
if (字母的判定条件) {
	// 转换后添加字母
}
// 添加数字

细节问题

回溯

回溯时的恢复现场操作是将 path 的最后元素删掉。

剪枝

本题是穷举了所有情况,因此不涉及剪枝操作。

递归出口

当遍历到字符串 s 的最后字符就需要更新结果了,然后返回即可。

代码实现

版本一

Java 复制代码
class Solution {
    List<String> ret;
    StringBuilder path;

    public List<String> letterCasePermutation(String s) {
        ret = new ArrayList<>();
        path = new StringBuilder();

        dfs(s, 0);
        return ret;
    }

    private void dfs(String s, int pos) {
        // 递归出口
        if (pos == s.length()) {
            ret.add(path.toString());
            return;
        }

        char ch = s.charAt(pos);
        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
            // 是字母,需要转换大小写
            // 添加小写字母
            if (ch >= 'A' && ch <= 'Z') path.append(ch += 32);
            else path.append(ch);
            dfs(s, pos + 1);
            path.deleteCharAt(path.length() - 1); // 回溯时恢复现场

            // 添加大写字母
            if (ch >= 'a' && ch <= 'z') path.append(ch -= 32);
            else path.append(ch);
            dfs(s, pos + 1);
            path.deleteCharAt(path.length() - 1); // 回溯时恢复现场
        } else {
            // 是数字,直接添加
            path.append(ch);
            dfs(s, pos + 1);
            path.deleteCharAt(path.length() - 1); // 回溯时恢复现场
        }
    }
}

版本二

Java 复制代码
class Solution {
    List<String> ret;
    StringBuilder path;
    
    public List<String> letterCasePermutation(String s) {
        ret = new ArrayList<>();
        path = new StringBuilder();
        
        dfs(s, 0);
        return ret;
    }

    private void dfs(String s, int pos) {
        // 递归出口
        if (pos == s.length()) {
            ret.add(path.toString());
            return;
        }
        
        char ch = s.charAt(pos);
        if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') {
            // 是字母,需要转换大小写
            path.append(deal(ch));
            dfs(s, pos + 1);
            path.deleteCharAt(path.length() - 1); // 回溯时恢复现场
        }
        
        // 是数字,不用转换直接添加
        path.append(ch);
        dfs(s, pos + 1);
        path.deleteCharAt(path.length() - 1); // 回溯时恢复现场
    }

    private char deal(char ch) {
        if (ch >= 'a' && ch <= 'z') return ch -= 32;
        else return ch += 32;
    }
}

文章到这里就告一段落啦,若有错误请尽管指出~

相关推荐
就叫_这个吧4 小时前
Java递归方法实现面包屑导航
java·开发语言
小O的算法实验室4 小时前
IEEE TASE,基于MPC的多无人机协同搜索竞争群体优化方法
算法
fīɡЙtīиɡ ℡4 小时前
AI 应用系统设计
java·开发语言·人工智能
城管不管4 小时前
重生——第十一次面试之挖财一面2026.8.19已OC
java·服务器·jvm·数据库·spring·面试·职场和发展
码匠许师傅4 小时前
【C++ 面试真题】26. 聊聊 C++ 的智能指针
java·c++·面试
AI绘画哇哒哒5 小时前
【建议收藏!】35岁后端血泪忠告,这3类人别硬转Agent(过来人亲述)
java·人工智能·后端·ai·程序员·大模型·agent
Tbisnic5 小时前
BGE-M3 算法详解:从模型架构到三种检索方式的数学原理
算法·自然语言处理·大模型·bert·transformer·注意力机制
最强小杰5 小时前
gpt-5.6-sol 频繁报 503 怎么办?区分容量熔断和限速 429 的排查方法 + 可复用 retry wrapper
java·人工智能·gpt·ai
Brilliantwxx5 小时前
【算法从零到千】【55-58】哈希位图+常见数学运算 接口
算法
空堂与归6 小时前
用户分群找不到规律?用K-Means聚类算法自动发现数据模式
算法·机器学习·kmeans·聚类