【剑指offer】【搜索和回溯】38. 字符串的排列

题目链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/

回溯1

class Solution {
public:
    vector<string> ans;
    string path;
    vector<string> permutation(string s) {
        path.resize(s.size()); //为path分配大小
        sort(s.begin(), s.end()); //对s进行排序
        dfs(s, 0, 0, 0); 
        return ans;
    }
    /*
    u: 当前枚举的位置
    start: 用二进制表示某个数是否存在 n个数,用0 ~ 2^(n - 1)表示某个数是否存在;当前这个数应该从哪里开始枚举,上一个数的下一位
    state: 存的是哪些数被用过    
    */
    void dfs(string &s, int u, int start, int state){
        //遍历完所有数字
        if(u == s.size()){ 
            ans.push_back(path);
            return ;
        }
        //如果是第一个数或者当前数与上一个的数字不同,从头开始枚举
        if(!u || s[u] != s[u - 1]) start = 0;
        //一个数字与上一个数字相同
        for(int i = start; i < s.size(); i++)
            if(!(state >> i & 1)) //判断某个数字是否被用过 state表示中第i位是否被用过
            {
                path[i] = s[u];
                dfs(s, u + 1, i + 1, state + (1 << i)); //1左移i位在加上去,相当于把state的第i位变为1
            }
    }
};

class Solution {
public:
    vector<string> res;
    string path = "";
    vector<string> permutation(string s) {
        sort(s.begin(), s.end());
        dfs(s, 0);
        return res;
    }
    void dfs(string& s, int u)
    {
        if(u == s.size())
        {
            cout << path <<" " << path.size() << endl;
            res.push_back(path);
            return ;
        }

        for(int i = 0; i < s.size(); i++)
        {
            //去重枚举的时候考虑
            if(i >= 1 && s[i] == s[i - 1]) continue;
            if(s[i] == ' ') continue;
            char ch = s[i];
            path += ch;
            s[i] = ' ';
            
            dfs(s, u + 1);
            
            s[i] = ch;
            path.pop_back();
        }
    }
};


回溯2

字符串不包含重复字符

  1. 求所有可能出现在第一个位置的字符,把第一个字符和后面所有的字符交换
  2. 固定第一个字符,求后面字符的排列(仍然按照1,2来求);
不包含重复字符
#include <iostream>
using namespace std;
const int N = 100010;
char a[N];
void dfs(char *pStr, char *pBegin)
{
    if(*pBegin == '\0') printf("%s ", pStr);
    else
    {
        for(char *pCh = pBegin; *pCh != '\0'; ++pCh)
        {
            swap(*pCh, *pBegin);
            dfs(pStr, pBegin + 1);
            swap(*pCh, *pBegin);
        }
    }
}
void permutation(char *s)
{
    if(s == nullptr) return ;
    dfs(s, s);
    printf("\n");
}

int main() {
    scanf("%s", &a);
    permutation(a);
    return 0;
}


class Solution {
public:
    vector<string>res;
    vector<string> permutation(string s) {
        int cursor=0;
        permutation(s,cursor);
        return res;
    }
    void permutation(string &s,int cursor){
        if(cursor==s.size() - 1){
            res.push_back(s);
        }
        else{
            for(int i=cursor;i<s.size();i++){
                if(judge(s,cursor,i))continue;  //从cursor开始,遍历不重复的字符
                swap(s[cursor],s[i]);
                permutation(s,cursor+1);
                swap(s[cursor],s[i]);
            }
        }
    }
    bool judge(string& s, int start, int end) {
        for (int i = start; i < end; ++i) {
            if (s[i] == s[end]) return true;
        }
        return false;
    }
};
posted @ 2020-04-29 18:22  NaughtyCoder  阅读(93)  评论(0)    收藏  举报