最近恶补算法的知识,写些常用的算法来练练手。先上源代码https://files.cnblogs.com/ivenxu/algorithm.zip,这个源代码包括了整个系列的代码,将不断更新。
有人在博客上做过推测,世界上只有10%的程序员能一次无错的把折半查找算法写出来。http://reprog.wordpress.com/2010/04/19/are-you-one-of-the-10-percent/ 这就是编程的魅力,非常简单东西做得完美也不容易。我也手发痒,所以就从这个算法开始。结果很不幸,我不是那10%的人:)
private static int RecurseSearch(int[] src, int subject, int low, int high)
{
int mid = (low + high) / 2;
if (low > high) return -1;
if (low == high)
{
if (src[mid] == subject) return mid;
}
if (src[mid] < subject)
{
return RecurseSearch(src, subject, mid + 1, high);
}
else if (src[mid] > subject)
{
return RecurseSearch(src, subject, low, mid - 1);
}
else
{
return mid;
}
}
public static int Search(int[] src, int subject)
{
int low = 0, high = src.Length - 1;
while (low <= high)
{
int mid = (low + high) / 2;
if (src[mid] < subject)
{
low = mid + 1;
}
else if (src[mid] > subject)
{
high = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
有一道网上的面试题衍生出来的。
//有一个N*N的矩阵, 里面有N*N个数,这个矩阵的每一行,每一列都是排序好的,下面是一
//个例子
//1 3 7 9
//2 5 13 14
//6 8 25 26
//20 24 30 40
这是一道变了的折半查找,思想是非常类似的。折半的经典是分治,按一半一半的来分。那么如何来分一个数组呢?下面上两幅图来说明:
在这里,任何一个N X N的数组都可以分成四个数组,按N的奇偶分别按图中所示划分。到N=1的时候就不能再分,这个也是递归的退出条件。这里的划分后唯一能确定的就是,任何在第一象限的数字都是小于等于划分的这个元素本身的。
代码:
private static void Search(int[][] src, int subject, int left, int top, int len, ref int row, ref int col)
{
if (src.Length > 0)
{
if (src.Length != src[0].Length) throw new ArgumentException("bad array!");
}
if (src.Length <= 0)
{
row = -1;col = -1;return;
}
if (len == 1)
{
if (src[top][left] == subject)
{
row = top;col = left;return;
}
else
{
row = -1;col = -1;return;
}
}
if (src[src.Length - 1][src.Length - 1] < subject)
{
row = -1;col = -1;return;
}
// Seperate the array to 4 sub arrary
int ulLeft, ulTop, ulLen, urLeft, urTop, urLen, llLeft, llTop, llLen, lrLeft, lrTop, lrLen;
if ((len) % 2 == 0)
{
// Up Left Quadrant
ulLeft = left;ulTop = top;ulLen = len / 2;
// Up Right Quandrant
urLeft = left + ulLen;urTop = top;urLen = len / 2;
// Low Left Quadrant
llLeft = left;llTop = top + ulLen;llLen = len / 2;
//Low Right Quadrant
lrLeft = left + ulLen;lrTop = top + ulLen;lrLen = len / 2;
}
else
{
// Up Left Quadrant
ulLeft = left;ulTop = top;ulLen = len / 2 + 1;
// Up Right Quandrant
urLeft = left + ulLen;urTop = top;urLen = len / 2;
// Low Left Quadrant
llLeft = left;llTop = top + ulLen;llLen = len / 2;
//Low Right Quadrant
lrLeft = left + ulLen;lrTop = top + ulLen;lrLen = len / 2 + 1 ;
}
if (src[ulLeft + ulLen - 1][ulLeft + ulLen - 1] == subject)
{
row = ulLeft + ulLen - 1;col = ulLeft + ulLen - 1;return;
}
if (src[ulLeft + ulLen - 1][ulLeft + ulLen - 1] > subject)
{
// Search in Up Left Quandrant
Search(src, subject, ulLeft, ulTop, ulLen, ref row, ref col);
}
else
{
// Search in Uper Right Quandrant
Search(src, subject, urLeft, urTop, urLen, ref row, ref col);
if (row == -1 && col == -1)
{
// Search in Low Left Quandrant
Search(src, subject, llLeft, llTop, llLen, ref row, ref col);
if (row == -1 && col == -1)
{
// Search in Low Right Quandrant
Search(src, subject, lrLeft, lrTop, lrLen, ref row, ref col);
}
if (row == -1 && col == -1) return;
}
}
}
}
复杂度:平均是log(N),最坏的情况是所要查找的数字始终在第四象限,复杂度为0.75log(N)。