[leetCode]剑指 Offer 38. 字符串的排列

解法
-
把字符串(abc)看成两部分:a|bc
- 第一个字符 a
- 剩余字符 bc
-
将第一个字符与剩余字符交换,列举出第一个位置所有可能出现的字符(3种: a,b, c)
-
求第二部分字符串的全排列,第二部分又可以看成两部分:
- 第一个字符
- 剩余部分
由于是处理相同的问题所以可以递归求解。
class Solution {
//set集合避免重复
private Set<String> ans = new HashSet<>();
public String[] permutation(String s) {
if(s == null || s == ""){
return new String[]{};
}
char[] chars = s.toCharArray();
permutation(chars, 0);
String[] a = new String[ans.size()];
int i = 0;
for(String each : ans){
a[i] = each;
++i;
}
return a;
}
private void permutation(char[] chars, int begin){
if(begin == chars.length){
ans.add(String.valueOf(chars));
}else{
for(int cur = begin; cur < chars.length; ++cur){//第一个字符与后面的字符做交换
exch(chars, cur, begin);
permutation(chars, begin + 1);//固定第一位字符,求剩余字符的全排列
exch(chars, cur, begin);//交换之后换回来
}
}
}
private void exch(char[] chars, int i, int j){
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
}
类似题目
组合
class Solution {
private List<List<Integer>> output = new LinkedList<>();
private int n;
private int k;
public List<List<Integer>> combine(int n, int k) {
if(n < k) return new LinkedList();
this.n = n;
this.k = k;
backTrack(1, new LinkedList<Integer>());
return output;
}
private void backTrack(int begin, LinkedList<Integer> cur){
if(cur.size() == k){
output.add(new LinkedList(cur));
}else {
for(int i = begin; i < n + 1; ++i){
cur.add(i);
backTrack(i+1, cur);
cur.removeLast();
}
}
}
}
组合总和
class Solution {
private List<List<Integer>> ans = new LinkedList<>();
private int[] candidates;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
if(candidates == null) return new LinkedList<>();
this.candidates = candidates;
backTrack(0, new LinkedList<Integer>(),target);
return ans;
}
private void backTrack(int begin, LinkedList<Integer> curr,int target){
if(target < 0)
return;
if(0 == target){
ans.add(new LinkedList<Integer>(curr));
return;
}
for(int i = begin; i < candidates.length; ++i){
curr.add(candidates[i]);
backTrack(i, curr, target - candidates[i]);
curr.removeLast();
}
}
}
组合总和||
class Solution {
private List<List<Integer>> ans = new LinkedList<>();
private int[] candidates;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if(candidates == null) return new LinkedList<>();
Arrays.sort(candidates);//先排序
this.candidates = candidates;
backTrack(0, new LinkedList<Integer>(),target);
return ans;
}
private void backTrack(int begin, LinkedList<Integer> curr,int target){
if(0 == target){
ans.add(new LinkedList<Integer>(curr));
return;
}
if (target< 0) {
return;
}
for(int i = begin; i < candidates.length; ++i){
if (i > begin && candidates[i] == candidates[i - 1]) {
continue;
}
curr.add(candidates[i]);
backTrack(i+1, curr, target - candidates[i]);
curr.removeLast();
}
}
}
组合总和|||
class Solution {
private List<List<Integer>> ans = new LinkedList<>();
private int k;
public List<List<Integer>> combinationSum3(int k, int n) {
this.k = k;
backTrack(1, new LinkedList(), n);
return ans;
}
private void backTrack(int begin, LinkedList<Integer> curr, int n){
if(k == curr.size() && n == 0){
ans.add(new LinkedList<Integer>(curr));
return;
}
if( n < 0){
return;
}
for(int i = begin; i <= 9; i++){
curr.add(i);
backTrack(i+1, curr, n - i);
curr.removeLast();
}
}
}
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何通过向量化技术比较两段文本是否相似?
· 35+程序员的转型之路:经济寒冬中的希望与策略
· JavaScript中如何遍历对象?
· 领域模型应用
· 记一次 ADL 导致的 C++ 代码编译错误
· 独立项目运营一周年经验分享
· 神解释:为什么程序员怕改需求?
· 一款开源免费、通用的 WPF 主题控件包
· 独立开发,这条路可行吗?
· 【定时任务核心】究竟是谁在负责盯着时间,并在恰当时机触发任务?