您的位置:首页 > 职场人生

面试中遇到的一道算法题,请各位对我的算法指点一下

2017-12-20 13:49 429 查看
前几天面试,遇到一题上机题,由于写了大半年的安卓控件,对于一些基础函数都有点生疏,面试结束后,面试官说我的算法一般般,不过现在也没有想到哪里可以优化。请各位指点一下。

面试题目是这样的:将输入的账户余额以读取的形式转化出来。例如:

输入:123.12

输出:One hundred twenty three dollars and twelve cents

注意:dollar和cent的复数形式,有没有and连接等。

我的思路就是把整数和小数部分分开,然后分别读取各个部分。

读取每个部分的时候,先将该部分字符串补全至3的倍数个(前面加0),然后以三个字符为一组进行读取,先读百位,再读剩下两位。

最后根据两个部分的值,看情况把两个部分连接起来。

我写了五个函数,分别是:

1、读取函数。功能是将输入的字符串划分为两个部分,然后使用别的函数读出这两个部分,最后视情况添加and。

/// <summary>
/// 如果输入的字符串是数字,则读出来
/// </summary>
/// <param name="amount"></param>
/// <returns></returns>
public static string read(string amount)
{
try
{
if (amount == null || amount.Equals(""))
{
throw new Exception("输入的数字为空,请输入一个有效数字。");
}

//分割为整数部分和小数部分
string[] aryAmount = amount.Split('.');
if (aryAmount.Length > 2)
{
throw new Exception($"输入的数字中包含{aryAmount.Length - 1}个“.”,请查证后再次输入。");
}

//如果只有整数部分
if (aryAmount.Length == 1)
{
string strLower = readOnePart(aryAmount[0], true).Trim();
return strLower.Substring(0, 1).ToUpper() + strLower.Substring(1, strLower.Length - 1);
}
else
{
//包含小数部分
if (aryAmount[0] == null || aryAmount[0].Equals(""))
{
//如果数字以“.”开头,就当它没有整数只有小数
string strLower = readOnePart(aryAmount[1], false).Trim();
return strLower.Substring(0, 1).ToUpper() + strLower.Substring(1, strLower.Length - 1);
}
else
{
string strLower = readOnePart(aryAmount[0], true).Trim() + " and " + readOnePart(aryAmount[1], false).Trim();
return strLower.Substring(0, 1).ToUpper() + strLower.Substring(1, strLower.Length - 1);
}
}
}
catch (Exception e)
{
throw e;
}
}

2、读取各个部分啦,这里要加dollar或cent,那么就添加了一个bool参数判断是整数部分还是小数部分。现在想想判断哪个部分可以放在上面第一步的函数里面。
/// <summary>
/// 读取整数或小数部分
/// </summary>
/// <param name="part">待读取的字符串</param>
/// <param name="isIntPart">是否是整数部分</param>
/// <returns></returns>
private static string readOnePart(string part, bool isIntPart)
{
try
{
//将这个部分按照每三位一个划分
List<string> lisParts = spiltThreeChars(part);

//依次读取每个部分,然后在每个部分后加上单位,比如dollars,cents
string strPartRead = "";

if (isIntPart)
{
#region 读取整数部分
string[] strIntegerUnit =
{
"", //0
" thousand", //1
" million", //2
" billion" //3
};

//读取整数部分,单位为billion,million,thousand,Dollar(s)
for (int i = 0; i < lisParts.Count(); i++)
{
string strTempThree = readThreeNumbers(lisParts[i]);
if (strTempThree != null || !strTempThree.Equals(""))
{
strTempThree += strIntegerUnit[lisParts.Count() -1 - i];
}
strPartRead += strTempThree;
}
//如果没有整数部分,就直接返回emptystring
if (strPartRead.Trim().Equals(""))
{
return strPartRead;
}

//根据数值,看dollar后面是否加s
if (strPartRead.Trim().Equals("one"))
{
strPartRead += " dollar";
}
else
{
strPartRead += " dollars";
}
return strPartRead;
#endregion
}
else
{
#region 读取小数部分
string strFloat = "";
if (lisParts.Count() == 0)
{
return "";
}
else if (lisParts.Count() == 1)
{
strFloat = readThreeNumbers(lisParts[0]);
}
else
{
throw new Exception("小数部分最多三位数,当前太多啦。");
}

//判断cent后面要不要加s
if (strFloat.Trim().Equals("one"))
{
return strFloat + " cent";
}
else
{
return strFloat + " cents";
}
#endregion
}
}
catch (Exception e) { throw e; }
}

3、读取三个一组的数字,这里写了两个函数,还有一个函数是读取[0,99]的数字
/// <summary>
/// 读取[0-100]范围的数字,其中包含了readUnitNumber方法
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
private static string readThreeNumbers(string v)
{
try
{
//取百位数字以及剩下的数字
int intHundred = 0;
int intRest = 0;
try
{
intHundred = int.Parse(v.Substring(0, 1));
intRest = int.Parse(v.Substring(1, 2));
}
catch (Exception e)
{
throw new Exception($"您的输入“{v}” 有误,请检查后再次输入。");
}

string strHundred = "";
string strRest = "";
if (intHundred != 0)
{
return readUnitNumber(intHundred) + " hundred" + readUnitNumber(intRest);
}
else
{
return readUnitNumber(intRest);
}
}
catch (Exception e)
{
throw e;
}

}

/// <summary>
/// 读取[0-99]范围的数字
/// </summary>
/// <param name="unit"></param>
/// <returns></returns>
private static string readUnitNumber(int unit)
{
try
{
if (unit <= 20)
{
#region 读取[0,20]区间的数字
switch (unit)

4000
{
case 0:
return "";
case 1:
return " one";
case 2:
return " two";
case 3:
return " three";
case 4:
return " four";
case 5:
return " five";
case 6:
return " six";
case 7:
return " seven";
case 8:
return " eight";
case 9:
return " nine";
case 10:
return " ten";
case 11:
return " eleven";
case 12:
return " twelve";
case 13:
return " thirteen";
case 14:
return " fourteen";
case 15:
return " fifteen";
case 16:
return " sixteen";
case 17:
return " seventeen";
case 18:
return " eighteen";
case 19:
return " ninteen";
case 20:
return " twenty";
default:
return null;

}
#endregion
}
else
{
#region 读取[21,99]区间的数字
//十位
int intTen = unit / 10;
//个位
int intUnitDigit = unit % 10;

switch (intTen)
{
case 2:
return " twenty" + readUnitNumber(intUnitDigit);
case 3:
return " thirty" + readUnitNumber(intUnitDigit);
case 4:
return " fourty" + readUnitNumber(intUnitDigit);
case 5:
return " fifty" + readUnitNumber(intUnitDigit);
case 6:
return " sixty" + readUnitNumber(intUnitDigit);
case 7:
return " seventy" + readUnitNumber(intUnitDigit);
case 8:
return " eighty" + readUnitNumber(intUnitDigit);
case 9:
return " ninty" + readUnitNumber(intUnitDigit);
default:
return null;
}
#endregion
}
}
catch (Exception e)
{
throw e;
}
}

4、将字符串用“0”补全至长度为三的倍数,然后划分为三个字符为单位的数组,放在list容器中。
/// <summary>
/// 将字符串按照三个字符一组划分
/// </summary>
/// <param name="part">待划分字符串</param>
/// <returns></returns>
private static List<string> spiltThreeChars(string part)
{
try
{
//将字符串长度补全为3的倍数,如果不是三的倍数就在开头补0
int intLess = part.Length % 3;
if (intLess != 0)
{
for (int i = 0; i < 3 - intLess; i++)
{
part = "0" + part;
}
}

//每三个字符一分割
List<string> lisThreeCharsArray = new List<string>();
char[] aryChars = part.ToArray();
for (int i = 0; i < aryChars.Length / 3; i++)
{
string strTemp = aryChars[i * 3].ToString() + aryChars[i * 3 + 1].ToString() + aryChars[i * 3 + 2].ToString();
lisThreeCharsArray.Add(strTemp);
}
return lisThreeCharsArray;
}
catch (Exception e)
{
throw e;
}
}

这基本就是我当时写的代码,然后面试官说一般,请问这题还有别的什么解决思路?请各位讨论一下。

最后附上整个类

class Dollars
{
/// <summary>
/// 如果输入的字符串是数字,则读出来
/// </summary>
/// <param name="amount"></param>
/// <returns></returns>
public static string read(string amount)
{
try
{
if (amount == null || amount.Equals(""))
{
throw new Exception("输入的数字为空,请输入一个有效数字。");
}

//分割为整数部分和小数部分
string[] aryAmount = amount.Split('.');
if (aryAmount.Length > 2)
{
throw new Exception($"输入的数字中包含{aryAmount.Length - 1}个“.”,请查证后再次输入。");
}

//如果只有整数部分
if (aryAmount.Length == 1)
{
string strLower = readOnePart(aryAmount[0], true).Trim();
return strLower.Substring(0, 1).ToUpper() + strLower.Substring(1, strLower.Length - 1);
}
else
{
//包含小数部分
if (aryAmount[0] == null || aryAmount[0].Equals(""))
{
//如果数字以“.”开头,就当它没有整数只有小数
string strLower = readOnePart(aryAmount[1], false).Trim();
return strLower.Substring(0, 1).ToUpper() + strLower.Substring(1, strLower.Length - 1);
}
else
{
string strLower = readOnePart(aryAmount[0], true).Trim() + " and " + readOnePart(aryAmount[1], false).Trim();
return strLower.Substring(0, 1).ToUpper() + strLower.Substring(1, strLower.Length - 1);
}
}
}
catch (Exception e)
{
throw e;
}
}

/// <summary>
/// 读取整数或小数部分
/// </summary>
/// <param name="part">待读取的字符串</param>
/// <param name="isIntPart">是否是整数部分</param>
/// <returns></returns>
private static string readOnePart(string part, bool isIntPart)
{
try
{
//将这个部分按照每三位一个划分
List<string> lisParts = spiltThreeChars(part);

//依次读取每个部分,然后在每个部分后加上单位,比如dollars,cents
string strPartRead = "";

if (isIntPart)
{
#region 读取整数部分
string[] strIntegerUnit =
{
"", //0
" thousand", //1
" million", //2
" billion" //3
};

//读取整数部分,单位为billion,million,thousand,Dollar(s)
for (int i = 0; i < lisParts.Count(); i++)
{
string strTempThree = readThreeNumbers(lisParts[i]);
if (strTempThree != null || !strTempThree.Equals(""))
{
strTempThree += strIntegerUnit[lisParts.Count() -1 - i];
}
strPartRead += strTempThree;
}
//如果没有整数部分,就直接返回emptystring
if (strPartRead.Trim().Equals(""))
{
return strPartRead;
}

//根据数值,看dollar后面是否加s
if (strPartRead.Trim().Equals("one"))
{
strPartRead += " dollar";
}
else
{
strPartRead += " dollars";
}
return strPartRead;
#endregion
}
else
{
#region 读取小数部分
string strFloat = "";
if (lisParts.Count() == 0)
{
return "";
}
else if (lisParts.Count() == 1)
{
strFloat = readThreeNumbers(lisParts[0]);
}
else
{
throw new Exception("小数部分最多三位数,当前太多啦。");
}

//判断cent后面要不要加s
if (strFloat.Trim().Equals("one"))
{
return strFloat + " cent";
}
else
{
return strFloat + " cents";
}
#endregion
}
}
catch (Exception e) { throw e; }
}

/// <summary>
/// 读取[0-100]范围的数字,其中包含了readUnitNumber方法
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
private static string readThreeNumbers(string v)
{
try
{
//取百位数字以及剩下的数字
int intHundred = 0;
int intRest = 0;
try
{
intHundred = int.Parse(v.Substring(0, 1));
intRest = int.Parse(v.Substring(1, 2));
}
catch (Exception e)
{
throw new Exception($"您的输入“{v}” 有误,请检查后再次输入。");
}

string strHundred = "";
string strRest = "";
if (intHundred != 0)
{
return readUnitNumber(intHundred) + " hundred" + readUnitNumber(intRest);
}
else
{
return readUnitNumber(intRest);
}
}
catch (Exception e)
{
throw e;
}

}

/// <summary>
/// 读取[0-99]范围的数字
/// </summary>
/// <param name="unit"></param>
/// <returns></returns>
private static string readUnitNumber(int unit)
{
try
{
if (unit <= 20)
{
#region 读取[0,20]区间的数字
switch (unit)
{
case 0:
return "";
case 1:
return " one";
case 2:
return " two";
case 3:
return " three";
case 4:
return " four";
case 5:
return " five";
case 6:
return " six";
case 7:
return " seven";
case 8:
return " eight";
case 9:
return " nine";
case 10:
return " ten";
case 11:
return " eleven";
case 12:
return " twelve";
case 13:
return " thirteen";
case 14:
return " fourteen";
case 15:
return " fifteen";
case 16:
return " sixteen";
case 17:
return " seventeen";
case 18:
return " eighteen";
case 19:
return " ninteen";
case 20:
return " twenty";
default:
return null;

}
#endregion
}
else
{
#region 读取[21,99]区间的数字
//十位
int intTen = unit / 10;
//个位
int intUnitDigit = unit % 10;

switch (intTen)
{
case 2:
return " twenty" + readUnitNumber(intUnitDigit);
case 3:
return " thirty" + readUnitNumber(intUnitDigit);
case 4:
return " fourty" + readUnitNumber(intUnitDigit);
case 5:
return " fifty" + readUnitNumber(intUnitDigit);
case 6:
return " sixty" + readUnitNumber(intUnitDigit);
case 7:
return " seventy" + readUnitNumber(intUnitDigit);
case 8:
return " eighty" + readUnitNumber(intUnitDigit);
case 9:
return " ninty" + readUnitNumber(intUnitDigit);
default:
return null;
}
#endregion
}
}
catch (Exception e)
{
throw e;
}
}

/// <summary>
/// 将字符串按照三个字符一组划分
/// </summary>
/// <param name="part">待划分字符串</param>
/// <returns></returns>
private static List<string> spiltThreeChars(string part)
{
try
{
//将字符串长度补全为3的倍数,如果不是三的倍数就在开头补0
int intLess = part.Length % 3;
if (intLess != 0)
{
for (int i = 0; i < 3 - intLess; i++)
{
part = "0" + part;
}
}

//每三个字符一分割
List<string> lisThreeCharsArray = new List<string>();
char[] aryChars = part.ToArray();
for (int i = 0; i < aryChars.Length / 3; i++)
{
string strTemp = aryChars[i * 3].ToString() + aryChars[i * 3 + 1].ToString() + aryChars[i * 3 + 2].ToString();
lisThreeCharsArray.Add(strTemp);

8a3e
}
return lisThreeCharsArray;
}
catch (Exception e)
{
throw e;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: