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

描述

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

示例1:

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

示例2:

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

提示:

  1. 字符都是英文字母。
  2. 字符串长度在[1, 9]之间。

 使用特定函数

from itertools import permutations  # 导入 permutations 函数
from typing import List  # 导入 List 类型

class Solution:
    def permutation(self, S: str) -> List[str]:
        # 生成字符串 S 的所有排列,并使用 set 去重
        lis = set(permutations(S))
        
        # 将每个排列转换为字符串,并存入列表中
        return ["".join(p) for p in lis]

 排列组合的应用(itertools库中的函数)

全排列函数permutations()

result=itertools.permutations(iterable,r)

其中result为对迭代对象处理之后返回的结果,数据类型为'itertools.permutations',如果需要的话,可以通过list()转化为列表。转化为列表之后的元素的数据类型为元组。元素默认排列顺序为迭代对象字典序上的从小到大(自行体会:>);

iterable为需要排列的迭代对象,包括列表、字符串、元组、字典(只对键进行全排列);

r为单个排列元素的长度,不修改的话,默认为迭代对象的元素个数。

全组合函数combinations()

result=itertools.combinations(iterable,r)

其中result为迭代对象处理之后返回的结果,数据类型为'itertools.combinations',如果需要的话,可以通过list()转化为列表。转化为列表之后的元素的数据类型为元组。元素默认排列顺序为按照迭代对象字典序上的从小到大;

iterable为需要排列的迭代对象,包括列表、字符串、元组、字典(只对键进行全组合);

r为单个排列元素的长度,必须修改,不然会报错。

回溯法

from typing import List  # 导入 List 类型

class Solution:
    def permutation(self, S: str) -> List[str]:
        S = sorted(S)  # 将字符串 S 转换为排序后的列表,以便处理重复字符

        def backtrace(index):
            if len(path) == len(S):  # 如果当前路径长度等于 S 的长度
                res.append("".join(path))  # 将路径转换为字符串并添加到结果中
                return
            for i in range(len(S)):  # 遍历 S 中的每个字符
                if S[i] == 0:  # 如果字符已经被使用过,跳过
                    continue
                if i > 0 and S[i] == S[i-1] and S[i-1] != 0:  # 跳过重复字符
                    continue
                path.append(S[i])  # 将字符添加到路径中
                temp = S[i]  # 保存当前字符
                S[i] = 0  # 标记字符为已使用
                backtrace(index + 1)  # 递归调用
                S[i] = temp  # 恢复字符
                path.pop()  # 移除路径中的最后一个字符

        path = []  # 存储当前路径
        res = []  # 存储结果
        backtrace(0)  # 开始回溯
        return res  # 返回结果

最强回溯算法总结

理论基础

回溯是递归的副产品,只要有递归就会有回溯,所以回溯法也经常和二叉树遍历,深度优先搜索混在一起,因为这两种方式都是用了递归。

回溯法就是暴力搜索,并不是什么高效的算法,最多再剪枝一下。

回溯算法能解决如下问题:

    组合问题:N个数里面按一定规则找出k个数的集合
    排列问题:N个数按一定规则全排列,有几种排列方式
    切割问题:一个字符串按一定规则有几种切割方式
    子集问题:一个N个数的集合里有多少符合条件的子集
    棋盘问题:N皇后,解数独等等

算法模板

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值