zoukankan      html  css  js  c++  java
  • 字符串的组合问题

    题目:衔接上题,如果不是求字符的所有排列而是求所有字符的组合呢?还是输入三个字符a,b,c,则他们的组合有a,b,c,ab,ac,bc,abc.其中ab和ba只能算一个组合。

    分析:组合问题也是可以用递归来解决的。首先,我们先来考虑这样一个问题,从M个不同字符中任取N个字符的所有组合,假设我们要求abc字符中任意两个字符的组合。也就是输入3个字符,求3个字符长度为2的组合。

    我们可以这么想。从第一个字符开始(也就是a),第一种情况,这个组合有a,那么剩下就2-1=1个字符和a组合了,要么是b,要么是c,分别组合成ab,ac。第二种情况,这个组合没有a,那么就剩下bc,由于规定的是2个字符的组合,也就只有bc了,这也是整个递归过程结束的条件。示意图如下:

    接下来我们再回归题目,要求的是所有字符的组合,也就是组合的长度是1,2,3...,思路其实是一样的,只是多了一个for循环,考虑组合长度1,2,3..多个情况。

    void Combination(char *String)
    {
        assert(String != NULL);
        int length = strlen(String);
        vector<char> result;
        //for循环对1,2,3...次的组合调用下面的Combination(String, i, result)打印出来
        for (int i = 1; i <= length; ++i)
            Combination(String, i, result);
    }
    
    void Combination(char *pString, int number, vector<char>& result)
    {
        assert(pString != NULL);
        //1.递归出口
        if (*pString == '')
            return;
        //2.符合的条件情况,一一打印
        if (number == 0)
        {
            //计数
            static int num = 1;
            cout << num++ << " :  ";
            //终止的时候就打印结果
            vector<char>::iterator iter = result.begin();
            for (; iter != result.end(); ++iter)
                cout << *iter << "  ";
            cout << endl;
            return;                                         //别掉了,每次打印完了后,就进行下一次的打印
        }
    
        //3.进行递归成小问题
        result.push_back(*pString);                         //保存结果
        Combination(pString + 1, number - 1, result);       //当包含结点的时候
        result.pop_back();                                  //pop是因为下面不包含改结点的时候,指向的pString应该是一样的。                 
        Combination(pString + 1, number, result);           //当不包含该结点的时候
    }

     扩展1---题目:输入两个整数n和m,从数列1,2,3...n中随意取几个数,使其和等于m,要求列出所有的组合。

    分析:这其实就是一个组合问题,只是条件要求不一样罢了

    #include "stdafx.h"
    #include <iostream>
    #include <vector>
    using namespace std;
    vector<int> result;
    void find_factor(int sum, int n)
    {
        //1.递归出口
        if (n <= 0 || sum <= 0)
            return;
        //2.输出找到的数
        if (sum == n)
        {
            for (vector<int>::iterator iter = result.begin(); iter != result.end(); ++iter)
                cout << *iter << "+";
            cout << n << endl;
        }
        //3.递归成小问题
        result.push_back(n);
        find_factor(sum - n, n - 1);  //n放在里面
        result.pop_back();
        find_factor(sum, n - 1);      //n不放在里面
    }
    int main(void)
    {
        int sum, n;
        cin >> sum >> n;
        cout << "所有可能的序列,如下:" << endl;
        find_factor(sum, n);
        return 0;
    }

    总结一下:对于一些递归问题,首先要想到怎么做去符合递归条件,比如,终止的条件是什么?子问题的解应能组合成整个问题的解?子问题可通过再次递归调用求解?

    一旦我们确定使用递归,那么整个算法包含这几个部分:1).递归出口     2)满足条件(那么我们就输出这些结果) 3)递归成小问题。

    参考:http://blog.sina.com.cn/s/blog_662234020101azp7.html

            http://blog.csdn.net/hackbuteer1/article/details/7462447

  • 相关阅读:
    17.异常(三)之 e.printStackTrace()介绍
    16.异常(二)
    15.异常(一)
    AuthCodeTool验证码
    FileUploadTool
    JdbcTool
    myeclipse-java项目转换成web项目
    中文注释乱码change
    css鼠标样式
    java script 弹出框
  • 原文地址:https://www.cnblogs.com/menghuizuotian/p/3801461.html
Copyright © 2011-2022 走看看