zoukankan      html  css  js  c++  java
  • 面试题38:字符串的排列(C++)

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

    题目描述

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

    题目示例

    示例:

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

    解题思路

    字符串排列和数字排列问题都属于回溯的经典问题

    具体过程可参考上图(图源https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/c-by-bu-hui-coding-44/

    STL:使用函数next_permutation(start,end)求得当前排列的下一个排列

    递归回溯(全排列):定义回溯函数back_track,在决策树上遍历,并维护每个点的属性,每当走到树的底层,其路径便是一全排列。需要注意的是当字符出现重复时,需要去重,在这里我们使用flag数组标识当前元素是否已被访问过,初始默认均未访问,即初始化0,当访问之后,则初始化为1。另外一点就是需要首先对字符串进行排序,以此来使重复的字符相邻。最后,当节点未被访问且相邻字符不是重复字符时,将该字符加入排列字符串中,依次递归遍历。

    交换法:如图所示,分割字符串"ABC",每个固定一个字符为一部分,其他字符为另一部分,再将固定字符与其他字符进行交换,依次遍历每个字符,再进行回溯递归。

    程序源码

    STL

    class Solution {
    public:
        vector<string> permutation(string s) {
            if(s.empty()) return {};
            sort(s.begin(), s.end());
            vector<string> res;
            res.push_back(s);
            while(next_permutation(s.begin(), s.end())){
                res.push_back(s);
            }
            return res;
        }
    };

    递归回溯

    class Solution {
    public:
        vector<string> res;
        vector<int> flag;
        vector<string> permutation(string s) {
            if(s.empty()) return {};
            sort(s.begin(), s.end());
            flag = vector<int>(s.size(), '0');
            string str = "";
            back_track(s, 0, str);
            return res;
        }
        void back_track(string s, int index,  string track)       {
            if (s.size() == track.size()) { //回溯结束条件
                res.push_back(track);
                return;
            }
            for (int i = 0; i < s.size(); i++) {
                if (flag[i] == '1') continue; //当前值已被使用,则跳过
                if(i-1 >= 0 && s[i] == s[i-1] && flag[i-1] == '1') continue; //当前值和前一个值相等,并且前一个值已被使用,则跳过,比如aab
                flag[i] = '1';
                back_track(s, index+1, track+s[i]);
                flag[i] = '0';
            }
        }
       
    };

    交换法

    class Solution {
    public:
        vector<string> permutation(string s) {
            if(s.empty()) return {};
            set<string> res; //去重
            back_track(s, 0, res);
            return vector<string>(res.begin(), res.end());
        }
        void back_track(string s, int begin, set<string> &res)
        {
            if(begin == s.size())
            {
                res.insert(s);
                return;
            }
            for(int i = begin; i < s.size(); i++)
            {
                swap(s[i], s[begin]); //做出选择
                back_track(s, begin + 1, res); //进入下次决策树
                swap(s[i], s[begin]); //撤回选择
            }
        }
    };
     

    参考文章

    https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/hui-su-fa-by-luo-jing-yu-yu/

    ----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
  • 相关阅读:
    如何让自己拥有两年工作经验
    示波器入门使用方法
    模板显式、隐式实例化和(偏)特化、具体化的详细分析
    Dynamics CRM 2013 初体验(5):Business Rule
    Tomcat搭建
    岁月,时光,现实
    数据结构之链表单向操作总结
    iptables学习笔记
    知无涯者(The Man Who Knew Infinity)
    Dynamics CRM2016 Web API之Expand related entities &amp; $ref &amp; $count
  • 原文地址:https://www.cnblogs.com/wzw0625/p/12618716.html
Copyright © 2011-2022 走看看