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

文章目录

一、题目

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

示例1:

输入:S = "qqe"

输出:["eqq","qeq","qqe"]

示例2:

输入:S = "ab"

输出:["ab", "ba"]

提示:

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

点击此处跳转题目

二、C# 题解

同题目 LeetCode 面试题 08.07. 无重复字符串的排列组合,进行剪枝:

  1. 元素 S[i] 与 S[n] 相同时,舍去;
  2. 所得为新结果时,才纳入 ans。

步骤 1 剪枝不完全,所以还需加上步骤 2。

csharp 复制代码
public class Solution {
    public string[] Permutation(string S) {
        List<string> ans = new List<string>();
        Partition(ans, new StringBuilder(S), 0);
        return ans.ToArray();
    }

    public void Partition(List<string> ans, StringBuilder sb, int n) {
        if (n == sb.Length) {
            ans.Add(sb.ToString());
            return;
        }
        HashSet<char> hs = new HashSet<char>();
        for (int i = n; i < sb.Length; i++) {
            if (hs.Contains(sb[i])) continue;
            hs.Add(sb[i]);
            (sb[i], sb[n]) = (sb[n], sb[i]);
            Partition(ans, sb, n + 1);
            (sb[i], sb[n]) = (sb[n], sb[i]);
        }
    }
}
  • 时间:140 ms,击败 71.43% 使用 C# 的用户
  • 内存:46.7 MB,击败 92.86% 使用 C# 的用户

另一种剪枝方式,用一个 Set 集合存放已经交换过的重复元素,即不让当前 S[n] 与已经交换过的字母再进行交换:

csharp 复制代码
public class Solution {
    public string[] Permutation(string S) {
        List<string> ans = new List<string>();
        Partition(ans, new StringBuilder(S), 0);
        return ans.ToArray();
    }

    public void Partition(List<string> ans, StringBuilder sb, int n) {
        if (n == sb.Length) { // 递归出口
            ans.Add(sb.ToString());
            return;
        }
        HashSet<char> hs = new HashSet<char>(); // 记录已交换过的元素
        for (int i = n; i < sb.Length; i++) {
            if (hs.Contains(sb[i])) continue;   // 该元素已被交换过,则跳过
            hs.Add(sb[i]);                      // 添加记录
            (sb[i], sb[n]) = (sb[n], sb[i]);
            Partition(ans, sb, n + 1);
            (sb[i], sb[n]) = (sb[n], sb[i]);
        }
    }
}
  • 时间:128 ms,击败 100.00% 使用 C# 的用户
  • 内存:46.38 MB,击败 78.57% 使用 C# 的用户
相关推荐
1 9 J8 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
passer__jw7672 小时前
【LeetCode】【算法】3. 无重复字符的最长子串
算法·leetcode
passer__jw7672 小时前
【LeetCode】【算法】21. 合并两个有序链表
算法·leetcode·链表
sweetheart7-72 小时前
LeetCode22. 括号生成(2024冬季每日一题 2)
算法·深度优先·力扣·dfs·左右括号匹配
__AtYou__3 小时前
Golang | Leetcode Golang题解之第557题反转字符串中的单词III
leetcode·golang·题解
2401_858286113 小时前
L7.【LeetCode笔记】相交链表
笔记·leetcode·链表
IT规划师4 小时前
开源 - Ideal库 - 常用枚举扩展方法(一)
开源·c#·.net core·ideal库·枚举转换
景鹤5 小时前
【算法】递归+回溯+剪枝:78.子集
算法·机器学习·剪枝
_OLi_5 小时前
力扣 LeetCode 704. 二分查找(Day1:数组)
算法·leetcode·职场和发展
丶Darling.5 小时前
Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)
c++·算法·动态规划·记忆化搜索·回溯