面试题 08.08. 有重复字符串的排列组合--回溯算法

2023-11-15

LeetCode

面试题 08.08. 有重复字符串的排列组合

有重复字符串的排列组合。编写一种方法,计算某字符串的所有排列组合

示例1:

输入:S = "qqe"
输出:["eqq","qeq","qqe"]

示例2:

输入:S = "ab"
输出:["ab", "ba"]

解法:回溯法

解题思路: 首先,要求一个字符串的各种组合,我们第一个想法肯定是通过for循环,那么for循环的层数是多少勒,应该是该字符串的长度,然后通过for循环来进行匹配,但是,我们应该要注意一个问题,在进行排列组合的时候,可能会出现重复的字符串,比如说

字符串S = aa

我们的for循环代码是这样的

for(int i=0; i<2; i++)
    for(int j=0; j<2; j++)
        if(i!=j)
            printf("%c%c\n",S[i],S[j]);

这时候,输出结果是这样的

aa
aa

也就是说会出现重复,所以我们发现了,在一层循环中,相同的字符会产生出相同的字符串,因此我们会对上面的代码这样修改

for(int i=0; i<2; i++)
{
    if(i>0 && S[i]==S[i-1])
        continue
    for(int j=0; j<2; j++)
    {
        if(j>0 && S[j]==S[j-1] && j-1!=i) //j-1!=i表示上一个字符并没有被前面一层循环使用时
            continue;
        if(i!=j)
            printf("%c%c\n",S[i],S[j]);
    }
}

这样输出结果就是

aa

根据这一思路,我们就可以用递归来解决这个问题,首先,我们要定义

boolean used[] //表示一个字符是否被使用,因为是在递归里,不能像for循环一样来规避相同位置的元素

完整代码:

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
class Solution {
    public String[] permutation(String S) {
        List<String> res = new ArrayList<String>();
        int len = S.length();
        if (len == 0) return new String[0];
        boolean[] used = new boolean[len];
        char[] sChar = S.toCharArray();

        StringBuilder path = new StringBuilder(len); 

        // 排序是为了后面的剪枝。其实剪枝就是我们for循环里边避免重复操作的那一步
        Arrays.sort(sChar);

        dfs(res, sChar, len, path, 0, used);
        return res.toArray(new String[0]);
    }
    
    /**
    * @param res 结果集
    * @param sChar 输入字符数组
    * @param len 字符数组长度
    * @param path 根结点到任意结点的路径
    * @param depth 当前树的深度
    * @param used 使用标记数组
    */
    private void dfs(List<String> res
                    , char[] sChar
                    , int len
                    , StringBuilder path
                    , int depth
                    , boolean[] used) {
        // 到达叶子结点
        if (depth == len) {
            res.add(path.toString());
            return;
        }

        for (int i = 0; i < len; i++) {
            if (!used[i]) {

                // 根据已排序字符数组, 剪枝
                if (i > 0 && sChar[i] == sChar[i-1] && !used[i-1]) {
                    continue;
                }

                path.append(sChar[i]);
                used[i] = true; // 标记选择
                dfs(res, sChar, len, path, depth+1, used);
                path.deleteCharAt(depth);
                used[i] = false; // 撤销选择
            }
        }
    }
}

解法来源

作者:miracle-131

链接:https://leetcode-cn.com/problems/permutation-ii-lcci/solution/hui-su-suan-fa-jian-zhi-9980-10000-by-miracle-131/
来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试题 08.08. 有重复字符串的排列组合--回溯算法 的相关文章

随机推荐

  • spring IOC流程图

    ioc核心 DefaultListableBeanFactory private final Map
  • 点云检测笔记2022

    目录 激光雷达综述 2022以前的点云检测 自动驾驶中的坐标系 Complex YOLOv4 激光雷达综述 百度安全验证
  • 记公司同事的一次集体活动

    花田游记 李维俊 杭州大区 风和日丽暖 春意现昂然 花田一日游 同事尽相伴 借着浓浓的春意在3月26日杭州大区组织到海上花田烧烤游玩 告别了城市的喧嚣 没有了工作的压力围绕在我们身边的只有体现同事之间紧密团队精神的欢声笑语 上午我们团队一行
  • Python优雅的日志——loguru

    loguru RECOMMENDATION 影视 loguru 据小提莫观察 在python的使用者中 善于聪明 偷懒 以及不重复造轮子已经成为大家的共识 正所谓 人生苦短 我用python 作为python的爱好者 肯定是喜欢python
  • 【分析】segments的version_map_memory指标具体表示什么?

    ES有很多的监控指标 其中有一些指标官方解释的实在模糊 比如version map memory byte units Total amount of memory used by all version maps across all s
  • JAVA 集合之迭代器Iterator

    Java语言中的Iterator功能比较简单 只能单向移动 它的主要功能有四种 1 凡是实现Collections接口的数据结构都可以使用该方法 第一次调用Iterator的next 方法时 它返回序列的第一个元素 2 使用next 获得序
  • 前哈工大教授开发的ChatALL火了!可同时提问17个聊天模型,ChatGPT/Bing/Bard/文心/讯飞都OK...

    丰色 发自 凹非寺量子位 公众号 QbitAI 今天的你 是否还在几个聊天大模型之间 反复横跳 毕竟各家训练数据和方法不尽相同 擅长和不擅长的东西也都不一样 现在 不用这么麻烦了 有人开发了一个名叫 ChatALL 的应用 可以将你的提问同
  • CTFShow Web7&Web8

    这两道题都是版本控制工具直接部署到生产环境中造成的信息泄露 所以在此一起总结 题目中给出了明显的提示 版本控制很重要 但不要部署到生产环境更重要 和备份文件泄露的题型一样 笔者自己的感觉是这种题型最常用的工具就是dirsearch 因此选择
  • C++类的默认成员函数 —— 析构函数

    一 概念 析构函数 与构造函数功能相反 析构函数不是完成对对象本身的销毁 局部对象销毁工作是由编译器完成的 而对象在销毁时会自动调用析构函数 完成对象中资源的清理工作 二 特征 析构函数是特殊的成员函数 其特征如下 1 析构函数名是在类名前
  • 物联网、区块链、元宇宙和虚拟数字人离普罗大众有多远?

    首先 我们最早理解的数字人就是数字虚拟的一个假人 可能看起来很像二次元玩偶的样子 今天我觉得数字人是一种虚拟的数字身份 无所谓你的形象是仿真或是任何形象 包括你在现实中无法实现的形象 你在梦想中所渴望的概念 无论它是什么样的 它是你在另外一
  • 微信小程序,计算时分秒时间差

    shijiancha function faultDate completeTime var stime Date parse new Date faultDate var etime Date parse new Date complet
  • r语言(总)(我命油我不油天)

    seq等间隔函数 seq from to by length out along with from to 为数值 表示开始和结束 by为数值 表示间隔 length out为数值 表示数列长度 along with为向量 表示数列长度与该
  • fabric基本概念

    Hyperledger fabric基本概念 首先fabric是由IBM贡献的超级账本框架 它是一个利用现有成熟的技术来组合而成的一个区块链技术的实现 它是一种允许可插拔实现各种功能的的模块化架构 它具有强大的容器技术 来承载各种主流语言来
  • C语言进阶——文件管理

    每当我们写好一段代码运行结束之后 再次运行的时候就会发现 之前在终端上输入的数据都会消失 那么如何把之前输入的数据保存下来呢 我们一般把数据持久化的方式有把数据存放在磁盘文件中 存放到数据库 打印等方式进行保存 使用文件我们可以直接将数据保
  • Mysql字符串处理函数详细介绍、总结

    1 ASCII str 返回字符的 ASCII 码值 返回值为字符串str 的最左字符 第一个字符 的数值 即取得最左字符的 ascii 码 假如str 为空字符串 则返回值为 0 假如 str 为 NULL 则返回值为 NULL ASCI
  • unity 不显示UI项,代码无法引用UI类

    如果在unity项目中遇到在Hierarchy面板右键发现没有ui这个选项 在vs里无法引用到UI类时可以进行以下操作 1 可以在unity的Project面板 选中Assets文件夹 右键选择 show in Explorer选项 开打资
  • vue3.0 新的api属性

    vue3 0 只需要升级vuecli4 0以上的版本就可以选择性的安装了 获取路由对象 import useRouter from vue router const router useRouter router push 即可调用路由跳转
  • 【转载】国内主要的量化交易平台及链接

    Bigquant 掘金 优矿 万矿 聚宽 米筐 真格 镭矿 量化云 点宽等 附 网站网址 Bigquant https bigquant com 掘金 https www myquant cn 优矿 https uqer io v3 com
  • java基础 基本包装类 System Math Array BigInteger BigDecimal

    基本类型包装类 1 1 基本类型包装类概述 在实际程序使用中 程序界面上用户输入的数据都是以字符串类型进行存储的 而程序开发中 我们需要把字符串数据 根据需求转换成指定的基本数据类型 如年龄需要转换成int类型 考试成绩需要转换成doubl
  • 面试题 08.08. 有重复字符串的排列组合--回溯算法

    LeetCode 面试题 08 08 有重复字符串的排列组合 有重复字符串的排列组合 编写一种方法 计算某字符串的所有排列组合 示例1 输入 S qqe 输出 eqq qeq qqe 示例2 输入 S ab 输出 ab ba 解法 回溯法