认认真真地写好一段代码,写好一个函数,也是很有乐趣的一件事情。
1. 比如说对于这样一个小题目:
在一50人的队列中,从左至右报数,为单数者出列,其他人再从左至右报数,为单数者出列,直至剩下最后一人,问此人是初始队列中的第多少号?
意看到这个描述,那么当然有一种顺理成章的做法,如下所示:
namespace Exam01
{
using System.Collections.Generic;
/// <summary>
/// TODO: Update summary.
/// </summary>
public class Utility
{
private List<int> numbers = new List<int>();
public Utility()
{
for (int i = 1; i <= 50; i++)
{
numbers.Add(i);
}
}
public int Run()
{
while (numbers.Count > 1)
{
int start =
((numbers.Count >> 1) << 1) == numbers.Count ?
numbers.Count - 1 :
numbers.Count;
for (int i = start - 1; i >= 0; i -= 2)
{
numbers.RemoveAt(i);
}
}
return numbers[0];
}
}
}
这个做法显然不是最优的。
经过简单的分析,我们可以看到,每一轮去除单数元素后,每次得到的新的数列中,第一个元素的值是很有规律的。这个规律就是2的n次方,n从0开始取值。
所以上面的Run()函数我们优化为下面这样的:
public int Run()
{
int start = 1;
int k = 50 >> 1;
while (start <= k)
{
start <<= 1;
}
return start;
}
再举两个代码优化的小例子:
2. 如何把月份转换成季度
先看一下某论坛帖子里面的代码:
public int ConvertMonthToQuarter(int month)
{
double f = Convert.ToDouble(month)/3f;
if (f > Convert.ToInt32(f))
{
return Convert.ToInt32(f) + 1;
}
return Convert.ToInt32(f);
}
这段代码当然质量是惨不忍睹的。下面是我的优化:
/// <summary>
/// Get quarter of the year by month value.
/// Notice: valid month range is [1 -- 12]
/// </summary>
/// <param name="month">month value.</param>
/// <returns>quarter value of the year</returns>
public int GetQuarterByMonth(int month)
{
if (month < 1 || month > 12)
{
string message = string.Format("Input parameter month ({0}) out of range[1 -- 12].", month);
throw new ArgumentOutOfRangeException("month", message);
}
int q = month / 3;
return q * 3 < month ? q + 1 : q;
}
然后,略微一思考,进一步优化如下:
/// <summary>
/// Get quarter of the year by month value.
/// Notice: valid month range is [1 -- 12]
/// </summary>
/// <param name="month">month value.</param>
/// <returns>quarter value of the year</returns>
public int GetQuarterByMonth(int month)
{
if (month < 1 || month > 12)
{
string message = string.Format("Input parameter month ({0}) out of range[1 -- 12].", month);
throw new ArgumentOutOfRangeException("month", message);
}
return (month - 1) / 3 + 1;
}
现在这个函数看起来终于像样了吧。
3. 获得本月份是本季度的第几个月
先看一下某论坛帖子里面的代码:
public int GetMonthOfQuarter(int month)
{
int num = month % 3;
if (num == 0)
{
return 3;
}
return num;
}
我对其优化如下:
/// <summary>
/// Get month sequence of the quarter.
/// Notice: valid month range is [1 -- 12]
/// </summary>
/// <param name="month">month value.</param>
/// <returns>month sequence of the quarter</returns>
public int GetMonthSeqOfQuarter(int month)
{
if (month < 1 || month > 12)
{
string message = string.Format("Input parameter month ({0}) out of range[1 -- 12].", month);
throw new ArgumentOutOfRangeException("month", message);
}
int k = (month - 1) / 3;
return month - 3 * k;
}
雕虫小技耳。但是也挺有意思。