算法刷题系列——回溯:784. 字母大小写全排列

问题描述

  1. 字母大小写全排列
    在这里插入图片描述

思路分析

首先这个题目要求的是全排列。那么就是无可避免地使用回溯法。这里建议对回溯的思想和经典的模板要熟悉。
那么这道题我其实并没有用求排列的方式,而是使用的组合。
二者的区别是:
1. 排列需要用used数组来标记该遍历的位置是否加入到结果集了;
2. 组合则不需要,因为下次递归的起始下标从当前遍历的位置的下一个位置开始。
二者的联系是:排列是从一个数组(n个元素)中选择1、2、3…n个数字的组合。
这道题为什么我没有采用排列的思路呢?因为我们无法确定递归终止的条件,因为结果中的元素并不允许位置上的变化
如果求组合,使用一个for循环指定每次需要选择的组合数,每次选择i个数转化大小写(组合过程)即可。
注意几点:

  1. 跳过非字符的位置;
  2. 递归的深度和遍历的下标并不是相等的,要分别记录(depth和idx)。

code

class Solution {
    
    
    public List<String> letterCasePermutation(String s) {
    
    
        List<String> res = new ArrayList();
        if (s.length() == 0) return res;
        res.add(s);
        char[] chs = s.toCharArray();
        int count = 0;
        for (int i = 0; i < chs.length; i++) {
    
    
            if (!isNum(chs[i])) count++;
        }
        if (count == 0)  return res;
        for (int j = 1; j <= count; j++) combine(chs, j, 0, 0 , res);
        return res;
    }
    // 求组合数的模板
    public void combine(char[] chs, int j, int depth, int idx, List<String> res) {
    
    
        if (depth == j) {
    
    
            res.add(new String(chs));
            return;
        }
        for (int i = idx; i < chs.length; i++) {
    
    
            char ch = chs[i];
            if (isNum(ch)) continue;
            exchange(chs, i);
            combine(chs, j, depth+1,i+1, res);
            exchange(chs, i);
        }
    }

    public boolean isNum(char ch) {
    
    
        return ch <= '9' && ch >= '0';
    }

    // 交换大小写
    public void exchange(char[] chs, int i) {
    
    
        if (chs[i] >= 97) chs[i] = (char)(chs[i] - 32);
        else chs[i] = (char)(chs[i] + 32);
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38684427/article/details/119335401