面试题38. 字符串的排列(较难)
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = “abc”
输出:[“abc”,”acb”,”bac”,”bca”,”cab”,”cba”]
限制:
1 <= s 的长度 <= 8
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof
思路:
本问题其实就是求所有字符的排列组合,针对这种问题,也可以利用回溯进行解决,但要求不能重复,因此需要进行剪枝。
比如字符串 abc ,如果让我们求所有排列,肯定是:
先固定第 1 位,从 a 、b 、 c 中选一个,比如 a。
在以 a 为第 1 位的前提下,固定第 2 位,从 b 、 c 中选一个,比如 b。
此时第 3 位也没有可以选择的余地了,只剩下 c,这一步就走完了。
退回第 2 步,依旧在第 2 位,这次选择 c 。
此时第 3 位也没有可以选择的余地了,只剩下 b,这一步也走完了。
退回第 1 步。
从上面,你可以总结出,正常的回溯,就是先走一条路,当结束后,退回上一步继续走,反复执行,直至退无可退,结束流程。
我们可以发现,最终是没有可以选择的余地,这在程序里可以理解为,运行到下一位时,不能使用之前使用过的数据,因此会涉及到字符交换。
但因为会进行回溯,所以数字可以在回溯后再换回去,从而不影响下一次的回溯。
那什么叫剪枝呢?就是要排除一些情况,针对本题,就是要排除重复的情况。
也就是在同一位置,不能出现两次相同的字符,因为第 2 次出现时,之前肯定已经针对这种情况,所有路线都已经走过了。
因此可以联想到使用集合,存储当前位置出现过的字符,如果重复,就可以直接跳过。
这里剪枝没搞定,需要回看重写
代码:
1 | class Solution { |