算法相关的书看的也有那么些了,对于解算法题也有点思路了,但自己真正动手写下的代码并不多。为了能快速看完一本书,一般都是只思考解题的思路,而没有自己亲手去写代码。当我想要把解题思路转换成具体的代码的时候,感觉那是相当拙计。
先从binary search开始吧,整理下从思考问题到具体写出代码的思路和方法。
按照Programming Pearls的思路,在写代码之前要明确问题定义,想出解决问题的算法及应该用到的数据结构。
下面先将我解决binary search问题的全部思维过程展现如下:
首先,大概知道binary search就是每次把要搜索的数组范围缩小一半,途中找到key所在的位置或者最终没有找到key(key不在数组中)。
这个从总体上看应该是用loop或者recursion来解决。
好像一下子想不出具体的思路,那就从可以想到的地方开始吧
数组长度是n,则key的index在[0, n-1]中。计算出中间位置的index m。若array[m]==key,则直接返回m,若array[m]>key则key在[m+1, n]中搜索,<的情况是对称的。然后循环进行这一过程。观察发现可用两个变量l,u代表要搜索的范围,这样可以再循环过程中更行l,u。伪代码如下:
l = 0, u = n - 1;
loop:
invariant: key只可能在[l, u]范围内
m = (l + u) /2;
if array[m] == key return m;
if array[m] > key u = m - 1;
if array[m] < key l = m + 1;
先考虑一下极端情况,看看有没有什么大的错误。u - l >= 2的时候没有什么异议。但当u = l + 1或u = l的时候m就会等于l,这正好得出了循环终止条件。加上循环终止条件伪代码如下:
l = 0, u = n - 1;
loop:
invariant: key只可能在[l, u]范围内
if (l > u) return -1;
m = (l + u) /2;
if (array[m] == key) return m;
if (array[m] > key) u = m - 1;
if (array[m] < key) l = m + 1;
将伪代码转化成C代码
int BSearch(int key, int* base, int size) {
int l = 0, u = size - 1;
int m;
while(true) {
if (l > u) return -1;
m = (l + u) / 2;
int tmp = base[m];
if (key == tmp) return m;
if (key > tmp) l = m + 1;
else u = m -1;
}
}
写代码的过程中要考虑到测试用例,也就是所谓的测试先行。这个思路没有考虑base是null的情况。
总结:
其实写代码也没有那么难,思路都是从无到有的,没法一下就写出代码就慢慢思考,从能想到的入手,代码就会一步步呈现在眼前。
写loop关键写对invariant和终止条件
坚持测试先行