zoukankan      html  css  js  c++  java
  • 字符串的排列

    时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M

    题目描述

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

    输入描述:

    输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

    思路:
      采用回溯法通过递归法实现,问题转换为先固定一个字符,求剩余字符的排列;求剩余字符的排列时跟原问题一样。
      1》遍历所有可能出现在第一个位置的字符(即,依次将第一个字符同后面的所有字符交换)
      2》固定第一个字符,求后面字符的排列(即,在第一个的遍历过程中,插入递归进行实现)
      注意:
        1》先确定递归结束的条件:本题中设begin==str.size()-1
        2》形如aba或aa等特殊测试用例的情况,vector在进行push_back时是不考虑重复情况的,需要自行控制。
        3》输出的排列可能不是字典顺序排列的,可能导致无法完全通过测试用例,考虑输出前排序,或者递归之后取消复位操作。
    class Solution {
    public:
        vector<string> Permutation(string str) {
            vector<string> result;
            if(str.empty())
                return result;
            Permutation(str,result,0);
            
            //此时得到的result中排序并不是字典顺序,需要单独排序
            sort(result.begin(),result.end());
            
            return result;
        }
        void Permutation(string str,vector<string>& result,int begin)
        {
            if(begin == str.size()-1)
            {
                if(find(result.begin(),result.end(),str)== result.end())
                {
                    //如果result中不存在str才添加,避免aa和aa重复添加
                    result.push_back(str);
                }
            }
            else
            {
                for(int i = begin;i < str.size();i++)
                {
                    // 第一次循环i与begin相等,相当于第一个位置自身交换,关键在于之后的循环,
                    // 之后i != begin,则会交换两个不同位置上的字符,直到begin==str.size()-1,进行输出;
                    swap(str[i],str[begin]);
                    Permutation(str,result,begin+1);
                    // 复位,用以恢复之前字符串顺序,达到第一位依次跟其他位交换的目的
                    swap(str[i],str[begin]);
                 }
            }
        }
        void swap(char &fir,char &sec)
        {
            char temp = fir;
            fir = sec;
            sec = temp;
        }
    };

       递归是方法,回溯是思想。

      回溯法:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。

      回溯法一般包括三个步骤:

      1》针对所给问题,定义问题的解空间

      2》确定易于搜索的解空间结构

      3》以深度优先搜索解空间,并可以在搜索过程中用剪枝函数避免无效搜索。

      回溯法是将原问题转换成一个个的子问题,采用树的形式进行解决,如下图所示。其实回溯法是深度优先搜索的一种,是“一条道走到黑”,再倒回到原点的的思想,因此最关键的也就是对上一个状态的保存,递归就是一个很好的实现方式。

     

  • 相关阅读:
    Day 20 初识面向对象
    Day 16 常用模块
    Day 15 正则表达式 re模块
    D14 模块 导入模块 开发目录规范
    Day 13 迭代器,生成器,内置函数
    Day 12 递归,二分算法,推导式,匿名函数
    Day 11 闭包函数.装饰器
    D10 函数(二) 嵌套,命名空间作用域
    D09 函数(一) 返回值,参数
    Day 07 Day08 字符编码与文件处理
  • 原文地址:https://www.cnblogs.com/whiteBear/p/12571294.html
Copyright © 2011-2022 走看看