剑指offer-28.全排列

Posted perfy576

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer-28.全排列相关的知识,希望对你有一定的参考价值。

0 题目

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

1 分析

这属于全排列算法。

 

假设,我们先选定第i个,为某个排序结果的第一个。那么只要将第i个元素,和第一个元素交换。然后继续全排列剩下的元素就行了。

因此有

vector<string> Permutation(string str)
{
    vector<string> ret;
    if (str.empty())
    {
        return ret;
    }

    // 相等的情况可以直接跳过
    // 所以做了排序
    sort(str.begin(), str.end());
    string tmp;
    aux(str, 0, tmp, ret);

    // 这里排序,因为和牛客的输出顺序不匹配所以排序
    sort(ret.begin(), ret.end());

    return ret;
}

void aux(string &str, int index, string &tmp, vector<string> &ret)
{
    if (index == str.size())
    {
        // 当 要开始全排列的index已经是 size() 了,那么表示,就不需要重拍了
        // 因此压入结果,返回
        ret.push_back(str);
        return;
    }

    for (int i = index; i < str.size(); ++i)
    {
        if (i != index && str[i] == str[index])
        {
            // 跳过重复的,重复的就不做了
            continue;
        }

        // 将选定的第一个交换过去,然后递归的全排列剩下的
        swap(str[index], str[i]);
        aux(str, index + 1, tmp, ret);

        // 这里在交换回去,也就是说,当以第i个为结果的第一个元素,遍历完以后
        // 以第i+1个为第一个元素遍历开始的时候,str与传入时候的顺序一样
        swap(str[index], str[i]);
    }
}

  

 

如果不采用这种交换的方式,可以采用memo的方式记录某个点是否加入,然后遍历完仍然需要回溯。

但是这样的化,在for中,就需要多次遍历一遍memo中的元素,因此,效率低。

以上是关于剑指offer-28.全排列的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer28 字符串的排列

剑指offer--28对称的二叉树

剑指offer28题

剑指 Offer 28. 对称的二叉树无取巧,易于理解!

剑指 Offer 28. 对称的二叉树无取巧,易于理解!

剑指 Offer 26. 树的子结构 / 剑指 Offer 27. 二叉树的镜像 / 剑指 Offer 28. 对称的二叉树 / 剑指 Offer 29. 顺时针打印矩阵