剑指 Offer 38. 字符串的排列(C++) 回溯法

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

示例:

输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]

限制:
1 <= s 的长度 <= 8

解题思路:

**和这个相似:**https://blog.csdn.net/qq_30457077/article/details/114375222
在这里插入图片描述
在这里插入图片描述
重复排列方案与剪枝:
当字符串存在重复字符时,排列方案中也存在重复的排列方案。为排除重复方案,需在固定某位字符时,保证 “每种字符只在此位固定一次” ,即遇到重复字符时不交换,直接跳过。从 DFS 角度看,此操作称为 “剪枝” 。

在这里插入图片描述
在这里插入图片描述

class Solution {
    
    
public:
    vector<string> permutation(string s) {
    
    
        dfs(s, 0);
        return res;
    }
private:
    vector<string> res;
    void dfs(string s, int x) {
    
    
        if(x == s.size() - 1) {
    
    
            res.push_back(s);                       // 添加排列方案
            return;
        }
        set<int> st;//首先vector属于顺序容器,其元素与存储位置与操作操作有关;
        //set属于关联容器,其元素相当于键值。set能够保证它里面所有的元素都是不重复的(multiset除外)。
        //因此,此处用set
        for(int i = x; i < s.size(); i++) {
    
    
            if(st.find(s[i]) != st.end()) continue; // 若s[i]存在于st,重复,因此剪枝
            st.insert(s[i]);//将 c[i] 加入 Set​ ,以便之后遇到重复字符时剪枝;
            swap(s[i], s[x]);                       // 交换,将 s[i] 固定在第 x 位;因为此处已经交换
            //,所以x == s.size() - 1时,执行res加入新元素
            /* if(x == s.size() - 1) {
            res.push_back(s);                       // 添加排列方案
            return;
        }
            */
            dfs(s, x + 1);                          // 开启固定第 x + 1 位字符
            swap(s[i], s[x]);                       // 恢复交换
        }
    }
};

复杂度分析:

在这里插入图片描述

作者:jyd
链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/mian-shi-ti-38-zi-fu-chuan-de-pai-lie-hui-su-fa-by/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/qq_30457077/article/details/114982754
今日推荐