zoukankan      html  css  js  c++  java
  • 剑指 Offer 38. 字符串的排列

    题目

    剑指 Offer 38. 字符串的排列

    我的思路

    如果原字符串的各个字符不相同,那么结果列表中字符串的个数是n!个,所以不论如何解决本题目,时间复杂度一定是n!。

    如果存在相同字符,那么搜索时需要“剪枝”。如何合理地剪枝?我原本的想法是用一颗字典树,空间复杂度会达到n!。但其实,在深搜时,递归调用已经隐含了树地层次结构,只需要在每个调用层中存储当前分支已搜索的子树节点即可,回溯并搜索另一个节点时此前的存储空间被释放。把空间复杂度降到了n*n。

    我的实现

    class Solution {
    public:
        vector<string> result;
        void dps(string rStr,string nStr){
            if(rStr.size()==0){
                result.push_back(nStr);
                return;
            }
            unordered_set<char> visited;
            for(int i=0;i<rStr.size();i++){
                if(!visited.count(rStr[i])){
                    visited.insert(rStr[i]);
                    string temp(rStr);
                    temp.erase(temp.begin()+i);
                    dps(temp,nStr+rStr[i]);
                }
            } 
            visited.clear();
        }
        vector<string> permutation(string s) {
            string init = "";
            dps(s,init);
            return result;
    
    
        }
    };
    /*
    可以以阶乘的复杂度遍历所有字符串排列,然后去重。
    去重的方法:用一个树形结构存储所有已经遍历的字符串排列
    时间复杂度n!;
    空间复杂度n!.
    
    可优化,如果使用深搜递归遍历,那么递归调用的过程其实是树向下探的过程,那么隐含的有一个树的结构。只需要在每一层调用设置一个辅助变量记录当前层已经遍历的字符,那么当前层就可以保证不遍历到重复的字符。而递归返回到高层时,同时会释放已访问过子树的结构,所以不需要随时记录一颗完整的树,降低了空间复杂度。
     
    */

    拓展学习

    我的解决方案中时通过选择剩余字符串中的某个字符,把它截取掉,从而得到新的剩余字符串。截取的过程其实会发生一段子串复制,式复杂度增加。官方题解中通过依次把剩余串中的首字符与其余字符交换的方式,只用只用交换两个字符元素就完成了选择当前位置字符的工作。

    class Solution {
    public:
        vector<string> result;
        vector<string> permutation(string s) {
            dfs(s, 0);
            return result;
        }
        void dfs(string& s, int pos) {
            if (pos >= s.size()) {
                result.push_back(s);
                return;
            }
            for (int i = pos; i < s.size(); ++i) {
                if (judge(s, pos, i)) continue;   // 如果pos和i之间有字符等于s[i],则跳过。
                swap(s[pos], s[i]);
                dfs(s, pos+1);
                swap(s[pos], 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;
        }
    };
  • 相关阅读:
    python3 与dict相关的魔法方法。使用于二叉搜索树的类中
    笔记:nestjs学习基础(1)
    ES6 --(10)class使用、class继承
    redux --(1)核心概念(stateaction educer)、三大原则、todolist with redux
    antV--G2 学习
    react源代码重点难点分析
    jQuery-ui源代码重点难点分析
    webuploader上传插件源代码重点难点分析
    破解jQuery Deferred()异步执行的神秘世界
    ueditor源代码重点难点分析
  • 原文地址:https://www.cnblogs.com/BoysCryToo/p/13535071.html
Copyright © 2011-2022 走看看