【算法-剑指 Offer】38. 字符串的排列(回溯;有重复元素的全排列)

剑指 Offer 38. 字符串的排列 - 力扣(LeetCode)

发布:2021年10月26日11:58:51

问题描述及示例

输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例:
输入:s = “abc”
输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]

提示:
1 <= s 的长度 <= 8

我的题解(回溯)

有关回溯也有一些通用的思路总结,可以看我下面博客中的相关描述:

参考:【算法-LeetCode】46. 全排列(回溯算法初体验)_赖念安的博客-CSDN博客

上面的博客中的【有关参考】部分也有我做的其他回溯题目,也可作为参考。

本题和我之前做过的一道回溯题目非常像:

参考:【算法-LeetCode】22. 括号生成(回溯;有重复元素的全排列)_赖念安的博客-CSDN博客

其中的相似点都是:需要在全排列的基础上考虑字符的重复性。所以说,这两道题的基本思路可以说是完全一致的。而这两道题都是在上面的『【算法-LeetCode】46. 全排列』的基础上演变而来的,所以只要掌握了全排列的思路,其他的排列组合问题就是在该基础上做一点演化即可(往往就是改变一点判断条件的事)。所以可以将这些排列组合类型的问题对照起来看,只要仔细观察就可以发现它们彼此之间的差别其实都只是其中的一两行代码而已。

在动手做这道题之前,我想起来之前似乎看到过一个『【算法-LeetCode】46. 全排列』的进阶版:『LeetCode 47. 全排列 II』,这个进阶版也是要考虑遍历对象中的重复元素。所以我就先去做了这道全排列的进阶题。

做下来后,我发现这道进阶题和本题其实是一模一样的。在这道全排列进阶题中,我提到了一些注意点,这些注意点也是区别并这类题目并灵活运用回溯解决问题的关键点

参考:【算法-LeetCode】47. 全排列 II(全排列进阶问题;回溯;有重复元素的全排列)_赖念安的博客-CSDN博客

相关的步骤和解释我就不多赘述了,在上面的博客中都有描述。

/**
 * @param {string} s
 * @return {string[]}
 */
var permutation = function(s) {
  let result = [];
  let temp = [];
  // 这里也可以不特意创建used,可以直接给backtracking的第二个参数传一个空数组
  // 因为undefined隐式转换为布尔值就是false
  let used = new Array(s.length).fill(false);
  backtracking(s, used)
  return result;

  function backtracking(s, used) {
    if(temp.length === s.length) {
      // 注意最后结果是要一个字符串,所以在将temp放入result前需要将其拼接成一个字符串
      result.push(temp.join(''));
      return;
    }
    for(let i = 0; i < s.length; i++) {
      // 注意下面这个判断条件,这是各个回溯题之间的差异点
      // 注意,因为字符串没有 some() 方法,所以需要先将子串运用split函数转为字符数组
      if(used[i] || s.slice(0, i).split('').some((cur, idx) => !used[idx] && cur === s[i])) {
        continue;
      }
      temp.push(s[i]);
      used[i] = true;
      backtracking(s, used);
      used[i] = false;
      temp.pop();
    }
  }
};


提交记录
执行结果:通过
52 / 52 个通过测试用例
执行用时:152 ms, 在所有 JavaScript 提交中击败了48.53%的用户
内存消耗:47.2 MB, 在所有 JavaScript 提交中击败了52.00%的用户
时间:2021/10/26 11:56

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年10月26日12:01:06

参考:字符串的排列 - 字符串的排列 - 力扣(LeetCode)

【更新结束】

有关参考

更新:2021年10月26日11:14:54
参考:【算法-LeetCode】47. 全排列 II(回溯;有重复元素的全排列)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】78. 子集(回溯)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】22. 括号生成(回溯;有重复元素的全排列)_赖念安的博客-CSDN博客

更新:2021年9月21日11:37:27
参考:【算法-LeetCode】46. 全排列(回溯算法初体验)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】93. 复原 IP 地址(回溯;递归)_赖念安的博客-CSDN博客
更新:2021年10月26日09:58:05
参考:算法——LeetCode22. 括号生成_知北行的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值