【回溯算法】【打卡第175道】:《剑指Offer》:JZ38 字符串的排列(字符串包含重复的元素)

1、题目描述

输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。

例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。

 

2、算法分析

回溯算法有组合,排序,子集,棋盘如N皇后等等。其实基本上理解就是递归的应用。本题属于排序。而且是字符串中字符的排序,还有数字的排序,其实都是一样的。序列中的是否重复元素看清楚题目。

这是一道排序算法题,回溯算法中的一种。

回溯算法其实是基于递归算法的,在递归的基础上回溯。注意,子结点向父节点进行回溯。

模板:

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

 回溯算法可以看成一个树型的结构。

①首先创建结果集合ArrayList,和StringBuilder存储每一个符合条件的路径。

②因为序列是经过拍过序的,所以比较每一层的ch[i] == ch[i-1],且used[i-1] == false说明元素在该层没有出现过。已经出现过的元素直接跳过,比如1,2,1,第一个1和第二个1都是重复的。

③重点来了:

// 如果元素没有出现过
            if(used[i] == false){
                // 设置为true代表已出现
                used[i] = true;
                // 集合中的path
                sb.append(String.valueOf(ch[i]));
                // 递归
                backTracking(ch,used);
                // 回溯,子结点向父节点回溯
                sb.deleteCharAt(sb.length()-1);
                // 因为是排序,后面的序列还要用,设置成false;
                used[i] = false;
            }

直接看代码:

3、代码实现

import java.util.*;
public class Solution {
    // 定义结果集
    ArrayList<String> result = new ArrayList<>();
    // 定义路径
    StringBuilder sb = new StringBuilder();
    public ArrayList<String> Permutation(String str) {
        char[] ch = str.toCharArray();
        // 对字符进行排序
        Arrays.sort(ch);
        // 定义元素是否使用过,used数组中默认值是false;
        boolean[] used = new boolean[ch.length];
        backTracking(ch,used);
        return result;
    }
    // 回溯函数
    public void backTracking(char[] ch,boolean[] used){
        if(sb.toString().length() == ch.length){
            result.add(sb.toString());
        }
        for(int i = 0;i < ch.length;i++){
            // 遍历每一层
            if(i > 0 && ch[i] == ch[i-1] && used[i - 1] == false){
                continue;
            }
            // 如果元素没有出现过
            if(used[i] == false){
                // 设置为true代表已出现
                used[i] = true;
                // 集合中的path
                sb.append(String.valueOf(ch[i]));
                // 递归
                backTracking(ch,used);
                // 回溯,子结点向父节点回溯
                sb.deleteCharAt(sb.length()-1);
                // 因为是排序,后面的序列还要用,设置成false;
                used[i] = false;
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值