程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 55. 2種方法求字符串的組合[string combination]

55. 2種方法求字符串的組合[string combination]

編輯:C++入門知識

【本文鏈接】

http://www.cnblogs.com/hellogiser/p/string-combination.html

題目】

題目:輸入一個字符串,輸出該字符串中字符的所有組合。舉個例子,如果輸入abc,它的組合有a、b、c、ab、ac、bc、abc。

分析

在之前的博文28.字符串的排列[StringPermutation]中討論了如何用遞歸的思路求字符串的排列。同樣,本題也可以用遞歸的思路來求字符串的組合。


 【遞歸法求組合】

可以考慮求長度為n的字符串中m個字符的組合,設為C(n,m)。原問題的解即為C(n, 1), C(n, 2),...C(n, n)的總和。對於求C(n, m),從第一個字符開始掃描,每個字符有兩種情況,要麼被選中,要麼不被選中。如果被選中,遞歸求解C(n-1, m-1);如果未被選中,遞歸求解C(n-1, m)。不管哪種方式,n的值都會減少,遞歸的終止條件n=0或m=0。

【代碼】

 C++ Code  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110   // 55_StringCombination.cpp : Defines the entry point for the console application.
//
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/5/24
*/

#include "stdafx.h"
#include <vector>
#include <iostream>
using namespace std;

// print string combination
void Print(vector<char> &result)
{
    vector<char>::const_iterator iterBegin = result.begin();
    vector<char>::const_iterator iterEnd = result.end();

    for (; iterBegin != iterEnd; ++ iterBegin)
        printf("%c", *iterBegin);
    printf("\n");
}

// get string combination recursively
// choose m chars from str
void Combination(char *str, unsigned int m, vector<char> &result)
{
    if(NULL == str || (*str == '\0' && m > 0))
        return;

    // base cases
    if (m == 0)
    {
        // we have got a combination,print it
        Print(result);
        return;
    }
    // (1)choose current char
    result.push_back(*str);
    // choose m-1 chars from remaining n-1 chars
    Combination(str + 1, m - 1, result);

    // (2) not choose current char
    result.pop_back();
    // choose m chars from remaining n-1 chars
    Combination(str + 1, m, result);
}

// string combination
void StringCombination(char *str)
{
    if(NULL == str || *str == '\0')
        return;
    int len = strlen(str);
    vector<char> result;
    for (int i = 1; i <= len; ++i)
        Combination(str, i, result);
}

void test_base(char *str)
{
    StringCombination(str);
    printf("---------------------\n");
}

void test_case1()
{
    char str[] = "";
    test_base(str);
}

void test_case2()
{
    char str[] = "a";
    test_base(str);
}

void test_case3()
{
    char str[] = "abc";
    test_base(str);
}

void test_main()
{
    test_case1();
    test_case2();
    test_case3();
}

int _tmain(int argc, _TCHAR *argv[])
{
    test_main();
    return 0;
}
/*
---------------------
a
---------------------
a
b
c
ab
ac
bc
abc
---------------------
*/

由於組合可以是1個字符的組合,2個字符的組合……一直到n個字符的組合,因此在函數void StringCombination(char *str)中,需要一個for循環。另外,用一個vector來存放選擇放進組合裡的字符。


 【位運算求組合】

另外本題還有一個巧妙的思路,可以從位運算出發求組合。用一個二進制數字,來決定字符的取捨,某一位為1,則取對應的字符,若為0則不取,就能夠實現字符組合。

例如對於“abc”,長度為3,則共有7種組合可能。讓num 從1自增到7,跟字符的每一位進行判斷,是否取捨。

比如:num=1,即001時:

(1)j指向第1個字符,(a>>j)&1==1,則取a;

(2)j指向第2個字符,(a>>j)&1==0,則捨棄b;

(3)j指向第3個字符,(a>>j)&1==0,則捨棄c;

此次組合的字符串為a;

以此類推。

當num=7,即111時:

(1)j指向第1個字符,(a>>j)&1==1,則取a;

(2)j指向第2個字符,(a>>j)&1==1,則取b;

(3)j指向第3個字符,(a>>j)&1==1,則取c;

此次組合的字符串為abc;

那麼當num依次取完所有的值,就可以得到所有的字符串組合。

【代碼】

 C++ Code  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28   /*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/5/24
*/
void StringCombinationUsingBitwise(char *str)
{
    // use bitwise operations to get string combination
    if(NULL == str || *str == '\0')
        return;
    int len = strlen(str);
    if (len >= 32)
        return;
    int sum = 1 << len;
    for (int i = 1; i < sum; ++i)
    {
        for (int j = 0; j < len; j++)
        {
            if ((i >> j) & 0x1)
            {
                // choose char at str[j]
                printf("%c", str[j]);
            }
        }
        printf("\n");
    }
}

相對於 【遞歸法求組合】【位運算求組合】速度更快,其時間復雜度為T=n*2n,但是n不能超過32.

【參考】

http://zhedahht.blog.163.com/blog/static/2541117420114172812217/

http://zhuyanfeng.com/archives/3246

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

http://blog.csdn.net/wuzhekai1985/article/details/6643127

 【本文鏈接】

http://www.cnblogs.com/hellogiser/p/string-combination.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved