【0】README
1)本文旨在review 算法分析的几个算法问题 附带源码;
【1】最大子序列和问题的解(两种解法——分治法+联机算法(推荐))
【1.1】分治法
1)intro:其思想是把问题分成两个大致相等的子问题,然后递归地对它们进行求解,这是“分”部分;“治”阶段 将两个子问题的 解合并到一起并可能再做些少量的附加工作,最后得到整个问题的解;
2)算法idea 描述:在我们的例子中(求最大子序列和的问题),最大子序列和可能出现在三个地方——或者整个出现在输入数据的左半部、或者整个出现在
2)算法idea 描述:在我们的例子中(求最大子序列和的问题),最大子序列和可能出现在三个地方——或者整个出现在输入数据的左半部、或者整个出现在
右半部、或者跨越输入数据的中部从而占据左右两半部分;
3)如何求其解呢? 前两种情况,可以递归求解,第3种情况的最大和可以通过求出前半部分的最大和(包含前半部分的最后一个元素)以及 后半部分的最大 和(包含后半部分的第一个元素)而得到。然后将这两个和加在一起;
4)算法流程演示和源码如下:
#include<stdio.h>#define ElementType intint max3(int i, int j, int k)
{if(i < j){i = j;}if(i < k){i = k;}return i;
}// compute the maximum sum of sebsequence.
// 3 in mxSubSum3 means 3 possibilities.
int maxSubSum3(int A[], int left, int right)
{int onlyLeftSum, onlyRightSum; // just only left or right sum without center.int centerLeftSum, centerRightSum; // the 3rd is passing center.int tempSum;int center, i;if(left==right){if(A[left] > 0){return A[left];}else{return 0;}}center = (left+right)/2; onlyLeftSum = maxSubSum3(A, left, center);onlyRightSum = maxSubSum3(A, center + 1, right);centerLeftSum = 0; tempSum = 0; for(i=center; i>=left; i--) { tempSum += A[i];if(tempSum > centerLeftSum){centerLeftSum = tempSum;}}centerRightSum = 0;tempSum = 0;for(i=center+1; i<=right; i++) { tempSum += A[i];if(tempSum > centerRightSum){centerRightSum = tempSum;}}printf("onlyLeftSum=%d, onlyRightSum=%d, centerLeftSum + centerRightSum=%d \n", onlyLeftSum, onlyRightSum, centerLeftSum + centerRightSum);return max3(onlyLeftSum, onlyRightSum, centerLeftSum + centerRightSum);
} int main()
{int N = 8, maxSum = 0; ElementType A[] = {4, -3, 5, -2, -1, 2, 6, -2}; maxSum = maxSubSum3(A, 0, N-1); printf("the maximum sum of array {4, -3, 5, -2, -1, 2, 6, -2} is: %d \n", maxSum);
}
【1.2】联机算法
1)intro:在任意时刻,算法对要操作的数据只需要读入一次,一旦被读入处理,它就不再需要被记忆了。而在处理过程中,算法对已读入的数据给出了正确的答案,具有这种特性的算法叫联机算法;
2)利用 联机算法求最大子序列和问题的解,源码如下(比 分治法效率高)
#include<stdio.h>#define ElementType int// 联机算法计算最大子序列和问题.
int maxSubSequenceSum(int A[], int N)
{int thisSum=0, maxSum=0;int j; for(j = 0; j < N; j++) {thisSum += A[j];if(thisSum > maxSum){maxSum = thisSum;}else if(thisSum < 0){thisSum = 0;}}return maxSum;
}int main()
{int N = 8, maxSum = 0; ElementType A[] = {4, -3, 5, -2, -1, 2, 6, -2}; maxSum = maxSubSequenceSum(A, N);printf("the maximum sum of array {4, -3, 5, -2, -1, 2, 6, -2} is %d \n", maxSum); return 0;
}
【2】运行时间中的对数
【2.1】荔枝1——二分查找
#include<stdio.h>#define ElementType int
#define NOTFOUND -1/* 二分查找,A[]升序排列 */
int binarySearch(ElementType A[], ElementType x, int N)
{int low, mid, high;low = 0;high = N - 1;while (low <= high){mid = (low + high) / 2;if(A[mid] < x){low = mid + 1;}else if(A[mid] > x){high = mid - 1; }else {return mid;}}return NOTFOUND;
} main()
{int A[]={4, 5, 67, 67, 109, 876};int N=6, x=109; printf("\narray[] = {4, 5, 67, 67, 109, 876}");printf("\nthe position whose value equals to %d is %4d\n", x, binarySearch(A, x, N));
}
【2.1】荔枝2——计算最大公因数(欧几里得 算法)
#include<stdio.h>#define ElementType int
#define NOTFOUND -1/* 求两个数的最大公因数(greatest common divisor) */
int gcd(int M, int N)
{int rem;printf("remainder sequence: ");while (N > 0){rem = M % N;M = N;N = rem;printf("%4d", rem);}return M;
}main()
{int N = 1989, M = 1590; int gcd_value;printf("\t\t\t ========== test for greatest common divisor ==========\n\n"); gcd_value = gcd(M, N);printf("\nthe greatest common divisor between %4d and %4d is %4d\n", M, N, gcd_value);}
【2.1】荔枝3——高效率的幂运算
1)减少乘法次数:如 X^62 只用到了9次乘法:
X^3=(X^2)*X , X^7=(X^3)^2*X , X^15=(X^7)^2*X , X^31=(X^15)^2*X , X^62=(X^31)^2
2 + 2 + 2 + 2 + 1 == 9次;
#include<stdio.h>int isEven(int N)
{return N % 2 == 0 ? 1 : 0;
}int pow(int x, int N)
{if(N == 0){return 1;}else if(N == 1){return x;}else if(isEven(N)) /* if(x) == if(N!=0) */{return pow(x * x, N / 2);}else{return pow(x * x, N / 2) * x;}
}void main()
{int x = 2, N = 7;long pow_ = pow(x,N);printf("\t\t\t ========== test for computing pow ==========\n");printf("\t\t\t result of %d^%d is %-6d\n", x, N, pow_);
}