算法练习:排列组合之翻译手机号码

问题描述

输入由数字组成的字符串,输出数字代表字母的所有组合。数字代表的字母参见手机9键英文输入键盘。

 

 

举例:

输入“23”,输出: “ad”,”ae”,”af”,”bd”,”be”,”bf”,”cd”,”ce”,”cf”。

 

问题分析

求解排列组合的问题,其解法固定,且代码统一。通常有两种方法:第一种是类似动态规划的分期摊还的方式,即保存中间结果,依次附上新元素,产生新的中间结果;第二种是递归法,通常是在递归函数里,使用for语句,遍历所有排列和组合的可能,然后在for语句内调用递归函数。

在这里,我们使用第一种方法:分期摊还。从数字字符串的第一个数字开始扫描,记录之前组合结果集,求出当前数字对应的多个字母,将每个字母依附至结果集中的每个组合中,产生新的结果集。

 

代码实现

#include <iostream>
#include <vector>
#include <string>
#include <ctime>
using namespace std;

string strMap[] = { "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };

typedef vector<string> StrArray;


int main()
{
	clock_t start,finish;
	double duration = 0.0; 


	string strNum;
	StrArray mStrResultVec;
	
	StrArray mStrTempVec;
	while( cin >> strNum )
	{
		///
		start = clock();
		/

		mStrResultVec.clear();
		mStrResultVec.push_back( "" );
		
		//采用分期摊还的方法求排列组合
		for( int i = 0; i < strNum.size(); ++i )
		{
			string strTemp = strMap[strNum[i]- '0'-1];
			mStrTempVec.clear();

			for( int j = 0; j < strTemp.size(); ++j )
			{
				for( int k = 0; k < mStrResultVec.size(); ++k )
				{
					mStrTempVec.push_back( mStrResultVec.at(k)+strTemp[j] );
				}
			}
			if ( !mStrTempVec.empty() ) mStrResultVec = mStrTempVec;
		}

		///
		finish = clock();    
		duration = (double)(finish-start);    
		cout << "时间消耗:" << duration << "ms" << endl << endl;  
		///
	}

	return 0;
}


 

以上代码可以做一个小优化,去除那个中间变量数组,从而优化性能

#include <iostream>
#include <vector>
#include <string>
#include <ctime>
using namespace std;

string strMap[] = { "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };

typedef vector<string> StrArray;


int main()
{
	clock_t start,finish;
	double duration = 0.0; 


	string strNum;
	StrArray mStrResultVec;

	//StrArray mStrTempVec;
	while( cin >> strNum )
	{
		///
		start = clock();
		/

		mStrResultVec.clear();
		mStrResultVec.push_back( "" );

		//采用分期摊还的方法求排列组合
		for( int i = 0; i < strNum.size(); ++i )
		{
			string strTemp = strMap[strNum[i]- '0'-1];
			//mStrTempVec.clear();
			int nCount = mStrResultVec.size();//保存之前结果集个数
			for( int j = 0; j < strTemp.size(); ++j )
			{
// 				for( int k = 0; k < mStrResultVec.size(); ++k )
// 				{
// 					mStrTempVec.push_back( mStrResultVec.at(k)+strTemp[j] );
// 				}
				for( int k = 0; k < nCount; ++k )
				{
					mStrResultVec.push_back( mStrResultVec.at(k)+strTemp[j] );
				}

			}

			//if ( !mStrTempVec.empty() ) mStrResultVec = mStrTempVec;
			//删除之前结果
			mStrResultVec.erase( mStrResultVec.begin(), mStrResultVec.begin()+nCount );
		}

		///
		finish = clock();    
		duration = (double)(finish-start);    
		cout << "时间消耗:" << duration << "ms" << endl << endl;  
		///
	}

	return 0;
}




系列文章说明:
1.本系列文章[算法练习],仅仅是本人学习过程的一个记录以及自我激励,没有什么说教的意思。如果能给读者带来些许知识及感悟,那是我的荣幸。
2.本系列文章是本人学习陈东锋老师《进军硅谷,程序员面试揭秘》一书而写的一些心得体会,文章大多数观点均来自此书,特此说明!
3.文章之中,难免有诸多的错误与不足,欢迎读者批评指正,谢谢.


作者:山丘儿
转载请标明出处,谢谢。原文地址:http://blog.csdn.net/s634772208/article/details/46708955


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值