全排列问题

22 篇文章 0 订阅
3 篇文章 0 订阅

全排列问题


leetcode 解法

思路:
Using an unordered_map to get all the distinct elements and the number of their occurence so that we don’t need to do sorting. Then do dfs and backtracking to generate all the permutations: for each iteration, put each available distinct element (i.e. numMap->second >0) into path, update numMap, and do DFS at the next level. Once path has a length of len, then we get a new permutation and just add path to res.

class Solution {
private: 
    void  dfsHelper(vector<vector<int>>  &res, vector<int> &path, unordered_map<int, int> &numMap, int len)
    {
        if(path.size()==len) {res.push_back(path); return;}
        for(auto it = numMap.begin(); it != numMap.end(); ++it)
        {
            if(it->second)
            {
                path.push_back(it->first); // update the current path
                --(it->second); // and map
                dfsHelper(res, path, numMap, len); // then do dfs at the next level
                path.pop_back(); // backtracking by recovering path and map
                ++(it->second);
            }
        }
    }

public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        int i,len = nums.size();
        vector<vector<int>> res;
        if(len>0)
        {
            vector<int> path;

            unordered_map<int, int> numMap; //generate a map
            for(i=0; i<len; ++i) ++numMap[nums[i]];

            dfsHelper(res, path, numMap, len);
        }
        return res;


    }
};

我的解法(思路和上面一样)

#include <stdio.h>
#include <vector>
#include <map>

using namespace std;

void solvepermute(vector<vector<int> >&res, vector<int> &ans, map<int, int> &M, int len);

vector<vector<int> > permuteUnique(vector<int>& nums) {
    map<int, int> M;           //定义一个map,用于保存某个数字,有多少个:如[1,1,2],则M[1]=2; M[2]=1;也就是1有2个,2有一个
    M.clear();
    for (int i=0; i<nums.size(); i++) {  //根据各定字符串,初始化map
        M[nums[i]]++;
    }
    vector<vector<int> > res;  //用于保存所有解
    vector<int> ans;           //用于保存单个解
    int len = nums.size();
    solvepermute(res, ans, M, len);
    return res;
}

void solvepermute(vector<vector<int> >&res, vector<int> &ans, map<int, int> &M, int len){
    if (ans.size()==len) {    //如果单个解的长度达到给定数组的长度,则该单个解push到解的集合中
        res.push_back(ans);
        return;
    }
    for (map<int, int>::iterator it = M.begin(); it!=M.end();++it) {
        if (it->second==0) {  //当map中key值对应的value为0时跳过
            continue;
        }
        ans.push_back(it->first);  //当map中key值对应的value不为0时,则把对应的key值push到单个解中,并把对应的value值减一
        it->second--;
        solvepermute(res, ans, M, len);
        ans.pop_back();            //回溯法,后面一定要恢复该位置,以便后续的取值。
        it->second++;

    }
}

int main(int argc, const char * argv[]) {

    vector<int> test = {1,1,2};
    vector<vector<int> > ans = permuteUnique(test);
    for (int i=0; i<ans.size(); i++) {
        for (int j=0; j<ans[0].size(); j++) {
            printf("%d ", ans[i][j]);
        }
        printf("\n");
    }
}
  • 需要学会使用map,用map来纪录每个元素有多少个相同元素
  • 使用回溯法来解,当单个解长度达到给定字符串长度时,则说明该解需要push到解的集合


#include <stdio.h>
#include <map>
#include <vector>
#include <string.h>

using namespace std;

void solvepermute(vector<vector<char> > &res, vector<char> &ans, map<char, int> &M, int len){
    int len_ans=int(ans.size());
    if (len_ans==len) {
        res.push_back(ans);
        return;
    }
    for (map<char, int>::iterator it = M.begin(); it!=M.end(); ++it) {
        if (it->second==0) {
            continue;
        }
        ans.push_back(it->first);
        (it->second)--;
        solvepermute(res, ans, M, len);
        ans.pop_back();
        (it->second)++;
    }
}

int main(int argc, const char * argv[]) {

    char s[7];
    while (scanf("%s", s)!=EOF) {
        int len = int(strlen(s));
        map<char, int> M;
        M.clear();
        for (int i=0; i<len; i++) {
            M[s[i]]++;
        }
        vector<vector<char> > res;
        vector<char> ans;
        solvepermute(res, ans, M, len);
        for (int i=0; i<res.size(); i++) {
            for (int j=0; j<res[0].size(); j++) {
                printf("%c", res[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

注意:以上代码会报超时,有待后续优化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值