leetcode面试题0808有重复字符串的排列组合

2023-09-20 17:58:23

描述

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

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

数据范围:n<10
要求:空间复杂度 O(n!),时间复杂度 O(n!)

输入描述:

输入一个字符串,长度不超过10,字符只包括大小写字母。

示例1

输入:"ab"

返回值:["ab","ba"]

说明:返回["ba","ab"]也是正确的

示例2

输入:"aab"

返回值:["aab","aba","baa"]

示例3

输入:"abc"

返回值:["abc","acb","bac","bca","cab","cba"]

示例4

输入:""

返回值:[""]

思路

 这道题就是一个组合,但是要排除重复项。如果直接使用循环,好像并不好下手。

 如果我们使用递归的思想,把字符串abc看作a和[bc]的组合。我们不用关心[bc]组合到底是什么样子,我们最终得到以a开头的组合就是a+[bc]。以b开头的组合b+[ac],以c开头的组合c+[ab]。

 在计算以a开头的组合中,我们还需要判断如果[bc]中有以a开头的字符。比如aab这种用例的情况,a+[ab],后面进行遍历的时候,我们就不再统计a,直接统计b+[aa]。所以最终结果就是aab aba,baa。

    大致思路其实已经出来了,伪代码如下:

permutation(abc) {
   list = [];
   set = [];
   for(a,b,c):
     if(!set.contains(a)){
       sublist = permutation(bc)
       for(String str: sublist):
          list.add(a+str)
       set.add(a);
     }
  return list;
}
     

    在上面aab的例子中,我们开始遍历a的时候,我们需要知道[ab]有多少种组合,这样,结果就是a + list([ab]) ,继续拆分ab,这时候就是a+list([b])。当只有一个字母的时候,组合就是一种情况,递归终止。当进行下一次遍历的时候,发现如果是a,那么不用遍历,因为a已经计算过。最后遍历到b,这时候就是b+list([aa]),继续拆分aa,同样是一种情况,最终遍历结束,返回所有的情况。

    同理,abc的时候,我们遍历a,我们需要知道剩下的[bc]的组合情况,继续拆分b+[c]。拆到只剩一个字母的时候,递归结束。接着遍历b、c。为了求出剩下的字符有多少种组合,我们继续拆分,也就是递归,直到剩下一个字母,这时候就是一种情况,递归结束。

    代码

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            System.out.println(Permutation(scanner.next()));
        }
        scanner.close();
    }

    public static ArrayList<String> Permutation(String str) {
        ArrayList<String> list = new ArrayList<>();
        if (str.length() == 1) {
            list.add(str);
        } else {
            Set<String> set = new HashSet<>();
            for (int i = 0; i < str.length(); i++) {
                String left = str.substring(i, i + 1);
                if (!set.contains(left)) {
                    String substr = str.substring(0, i) + str.substring(i + 1);
                    List<String> subList = Permutation(substr);
                    for (int j = 0; j < subList.size(); j++) {
                        list.add(left + subList.get(j));
                    }
                    set.add(left);
                }
            }
        }
        return list;
    }
}

    运行测试用例:

    这道题采用了递归的思想,把字符串拆分为首字母和剩下的子串,这种组合就是首字母和子串列表的组合。 为了求得子串有多少种组合,继续拆分,直到拆分到剩下一个字符串,这时候就是一种情况,拆分结束。当然,字符串有可能会有字母重复,我们在遍历的时候,记录是否已经遍历过当前首字母。

    还有一种比较孬的办法,这里不用考虑重复,把所有可能的情况都添加进来,最后把结果放到Set集合中,让它自己去重,虽然也能得到结果,但是时间复杂度不一定能满足算法要求。

    而本例的方法是通过了算法测试要求的:

    这种使用递归的办法,我们不需要知道每一种组合到底有多少种,我们只需要根据我们的思路去把字符串拆分成更小的单元,到了一个字母组成的字符串的时候,我们就很明确地知道这种组合情况,递归结束。 

  最后附上牛客网该题的地址:https://www.nowcoder.com/practice/fe6b651b66ae47d7acce78ffdd9a96c7

更多推荐

内网IP端口提供外网连接访问?快解析动态域名与内网映射P2P穿透方案

我们在本地搭建服务器及发布互联网时,可以通过动态域名的方式联网。DDNS原理是用固定的域名代替变化IP,实现局域网发布公网,是适合本地动态IP环境的使用。但当本地没有公网IP时,如果解析绑定到内网IP,将内网IP端口提供外网连接访问?这时我们就需要用到内网映射的方式了。动态域名与内网映射是二种不同的方法,分别针对动态公

Apache Hive安装部署详细图文教程

目录一、ApacheHive元数据1.1HiveMetadata1.2HiveMetastore二、Metastore三种配置方式​2.1内嵌模式​2.2本地模式​2.3远程模式​三、Hive部署实战3.1安装前准备3.2Hadoop与Hive整合3.3远程模式安装3.3.1安装MySQL3.3.2Hive安装3.4启

汉威科技亮相2023上海传感器展,智能传感新品引关注

作为全球三大传感器展之一的中国(上海)国际传感器技术与应用展览会,被誉为全球传感器行业发展的风向标,每届展会都会展出数以万计的行业尖端传感新技术和新产品。今年,第8届中国(上海)国际传感器技术与应用展览会于9月13至15日在上海跨国采购会展中心起航。此次展会上,车载传感、激光和柔性传感等智能传感领域的新品受到了关注。近

100天精通Python(可视化篇)——第99天:Pyecharts绘制多种炫酷K线图参数说明+代码实战

文章目录专栏导读一、K线图介绍1.说明2.应用场景二、配置说明三、K线图实战1.普通k线图2.添加辅助线3.k线图鼠标缩放4.添加数据缩放滑块5.K线周期图表书籍推荐专栏导读🔥🔥本文已收录于《100天精通Python从入门到就业》:本专栏专门针对零基础和需要进阶提升的同学所准备的一套完整教学,从0到100的不断进阶

【Python 数据科学】Dask.array:并行计算的利器

文章目录1.什么是Dask.array?1.1Dask简介1.2Dask.array概述1.3Dask.array与Numpy的对比2.安装与基本用法2.1安装Dask库2.2创建Dask数组2.3数组计算与操作3.Dask.array的分块策略3.1数组分块的优势3.2调整分块大小3.3数据倾斜与rebalance4

OpenMMLab MMYOLO目标检测应用示例与常见问题(三)

基于MMYOLO的电离图实时目标检测基准数据集数字电离图是获取实时电离层信息的最重要方式。电离层结构检测对于准确提取电离层关键参数具有重要的研究意义。本研究利用中国科学院在海南、武汉和怀来获得的4311张不同季节的电离图建立数据集。使用labelme手动注释包括LayerE、Es-l、Es-c、F1、F2和Spread

【SpringBoot系列】Spring cloud Gateway 动态路由到底有多简单

🤵‍♂️个人主页:@香菜的个人主页,加ischongxin,备注csdn✍🏻作者简介:csdn认证博客专家,游戏开发领域优质创作者,华为云享专家,2021年度华为云年度十佳博主🐋希望大家多多支持,我们一起进步!😄如果文章对你有帮助的话,欢迎评论💬点赞👍🏻收藏📂加关注+系列文章:SpringBoot学习大

Hdoop伪分布式集群搭建

文章目录Hadoop安装部署前言1.环境2.步骤3.效果图具体步骤(一)前期准备(1)ping外网(2)配置主机名(3)配置时钟同步(4)关闭防火墙(二)正文(1)配置hosts列表(2)SSH免密钥登录配置①master虚拟机上②slave01虚拟机上③slave02虚拟机上④验证免密登录(3)安装JDK(4)安装部

机器学习实战(01)-人工智能概要

1发展历程20世纪50年代:人工智能概念诞生1956年,“人工智能”这个术语由麦卡锡在达特茅斯会议上首次提出主要研究逻辑和推理,以及如何在机器上模拟人类智能20世纪60年代:知识表达期开始研究知识表达,使用谓词逻辑来表达知识开发可以解题的专家系统,例如Dendral专家系统20世纪70年代:知识库期研究汇集知识到知识库

vector类(顺序表)

文章目录1.定义:接口成员函数构造成员函数析构函数赋值2.迭代器2.1begin()和end()重点2.1.1应用2.1.1.1函数调用2.1.1.2用变量接受迭代器2.2rbegin()和rend()2.2.1应用3.顺序表的访问(增删查检)3.1operator[]和at3.2front()3.3back()4.v

突破视觉边界:深入探索AI图像识别的现状与挑战

图像识别作为人工智能领域的一个重要研究方向,取得了许多令人瞩目的成就。深入探索当前AI图像识别技术的现状以及所面临的挑战,讨论各种方法的优势和局限性。目录引言1.1AI图像识别的背景和概述1.2人工智能在图像识别中的应用和重要性图像识别基础知识2.1数字图像和像素2.2特征提取和表示2.3图像分类和目标检测传统图像识别

热文推荐