leecode 解题总结:273. Integer to English Words

#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <unordered_map>
#include <sstream>
using namespace std;
/*
问题:
Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 231 - 1.

For example,
123 -> "One Hundred Twenty Three"
12345 -> "Twelve Thousand Three Hundred Forty Five"
1234567 -> "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven"

分析:
这是程序员面试金典的一道题目。
以每1000位(thousand),1000 000(million百万), 1000 000 000(billion 十亿)做区分,然后读取
0~9: Zero One Two Three Four Five Six Seven Eight Nine 
10~19:Ten Eleven Twelve Thirteen Fourteen Fifteen Sixteen Seventeen Eighteen Ninteen
20,30,...90:Twenty,Thirty,Fourty,Fifty,Sixty,Seventy,Eighty,Ninety
100:hundred
1000:thousand

1234567: 1 234 567
One Billion Two Hundred Trirty Four Thousand Five Hunded Sixty Seven
2 147 483 647
Two Billion One Hundred Fourty Seven Million Four Hundred Eighty Three Thousand Six Hundred Fourty Seven

zero似乎只有为0的时候才读取

每三位一划分,划分为组,从最低位的组到最高位的组,依次加上组的后缀:
第一组:空
第二组:Thousand
第三组:Million
第四组:Billion
然后对于每一组:生成其读数:
如果是一位数:选取0~9对应的英文
如果是两位数:如果 < 20,选取10~19对应的英文
             否则,拆分出十位,个位:十位从20,30,...90中选取对应的数读取,个位如果为0:不需要继续处理
			       个位不为0,从个位数中选取对应的数字
如果是三位数:先拆分出百位上对应数值,从对应各位中读取该数值并添加Hundred ,拆分出的十位数同上面十位数的处理方式


输入:
2
15
30
91
100

101
123
1123
12345
212345

1234567
2147483647
1000
10000
1000000
1000000000

3055000
输出:
Two
Fifteen
Thirty
Ninety One
One Hundred

One Hundred One
One Hundred Twenty Three
One Thousand One Hundred Twenty Three
Twelve Thousand Three Hundred Forty Five
Two Hundred Twelve Thousand Three Hundred Forty Five

One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven
Two Billion One Hundred Fourty Seven Million Four Hundred Eighty Three Thousand Six Hundred Fourty Seven
One Thousand
Ten Thousand
One Million
One Billion

Three Million Fifty Five Thousand

报错:Forty写成Fourty,19拼错,Nineteen,我写成了Ninteen
Input:1000
Output:"One Thousand Zero Hundred"
Expected:"One Thousand"
划分成的每一组三位优先判断如果为0,则无需处理。但是如果本身是个位数0,则直接输出
划分后的值转化为int,个位数直接比较

关键:
1 还是逐一获取每个位置上的数,每3位划分为一组,添加后缀
2 Forty写成Fourty,19拼错,Nineteen,我写成了Ninteen
3 除了数字0本身,每一组中的0不做处理
4 还是不要转化为字符串
*/

class Solution {
public:

	void init()
	{
		//初始化个位
		string ones[10]= {"Zero", "One", "Two", "Three", "Four" ,"Five", "Six" ,"Seven", "Eight", "Nine"};
		_vecOnes.clear();
		_vecOnes.insert(_vecOnes.begin() , ones  , ones + 10);

		//初始化10~19
		string ten[10] = {"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen" ,"Eighteen", "Nineteen"};
		_vecTen.clear();
		_vecTen.insert(_vecTen.begin() , ten , ten + 10);

		//初始化20,30,...,90,Forty才是正确的,Fourty错误
		string tens[8] = {"Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
		_vecTens.clear();
		_vecTens.insert(_vecTens.begin() , tens, tens + 8);

		//初始化后缀
		string suffixStrs[4] = {"" , "Thousand" , "Million" , "Billion"};
		_vecSuffixStrs.clear();
		_vecSuffixStrs.insert(_vecSuffixStrs.begin() , suffixStrs , suffixStrs + 4);
	}

	//对当前的数字进行处理,至多包含两位
	string process(string& partialNum)
	{
		//如果是个位数
		int value = atoi(partialNum.c_str());
		int size = partialNum.size();
		//应该是用数值比较,比如“00”这种长度为2,但是实际表示个位数
		if(value < 10)
		{
			return _vecOnes[value];
		}
		//如果是十位数,那么就需要判断,选取后两位,因为第一位可呢过为0
		else if(10<= value && value <= 99)
		{
			if(value < 20)
			{
				return _vecTen[value - 10];
			}
			else
			{
				stringstream stream;
				//十位
				int tenValue = partialNum.at(size - 2) - '0'; //20,30,40,
				stream << _vecTens[tenValue - 2];
				//个位
				int oneValue = partialNum.at(size - 1) - '0';
				if(oneValue != 0)
				{
					stream << " " << _vecOnes[oneValue];
				}
				return stream.str();
			}
		}
		return "";
	}

    string numberToWords(int num) {
		if(0 == num)
		{
			return "Zero";
		}
		string sNum = to_string(num);
		if(sNum.empty())
		{
			return "";
		}
		init();


		//先把整数划分成组,每三位一组,从低到高处理
		int len = sNum.length();
		vector<string> result;
		int groupNum = 0;
		string partialNum;
		int hundredValue;
		string tempResult;
		for(int i = len - 1 ; i >= 0 ; i -= 3 )
		{
			stringstream stream;
			//将三位数进行处理,截取出这个三位数
			if(i - 2 >= 0)
			{
				partialNum = sNum.substr(i-2 , 3);
			}
			else if(i - 1 >= 0)
			{
				partialNum = sNum.substr(i-1 , 2);
			}
			else
			{
				partialNum = sNum.substr(i , 1);
			}

			//如果是个位数
			int value = atoi(partialNum.c_str());
			//如果当前为0,则无需处理,参见1000,直接为One Thousand
			if(0 == value)
			{
				groupNum++;
				continue;
			}
			//如果是<100,两位数
			if(value < 100)
			{
				tempResult = process(partialNum);
			}
			//三位数,获取百位
			else
			{
				hundredValue = partialNum.at(0) - '0';
				partialNum = partialNum.substr(1 , 2);
				stream << _vecOnes.at(hundredValue) << " Hundred";
				//如果后面两位为"00",无需处理
				if(0 != atoi(partialNum.c_str()))
				{
					tempResult = process(partialNum);
					if(!tempResult.empty())
					{
						stream << " " << tempResult;
					}
				}
				tempResult = stream.str();
			}
			if(groupNum != 0)
			{
				result.push_back(tempResult + " " +  _vecSuffixStrs.at(groupNum++));
			}
			else
			{
				result.push_back(tempResult +  _vecSuffixStrs.at(groupNum++));
			}
		}
		//result中存储的结果需要逆序输出,并添加" "
		if(result.empty())
		{
			return "";
		}
		int size = result.size();
		stringstream resultStream;
		for(int i = size - 1; i >= 0 ; i--)
		{
			if(i != size - 1)
			{
				resultStream << " " <<  result.at(i) ;
			}
			else
			{
				resultStream << result.at(i);
			}
		}
		return resultStream.str();
    }
private:
	vector<string> _vecOnes;
	vector<string> _vecTen;
	vector<string> _vecTens;
	vector<string> _vecSuffixStrs;
};

void print(vector<int>& result)
{
	if(result.empty())
	{
		cout << "no result" << endl;
		return;
	}
	int size = result.size();
	for(int i = 0 ; i < size ; i++)
	{
		cout << result.at(i) << " " ;
	}
	cout << endl;
}

void process()
{
	 int num;
	 Solution solution;
	 while(cin >> num )
	 {
		 string answer = solution.numberToWords(num);
		 cout << answer << endl;
	 }
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值