赞
踩
若采用常规方法逐次计算x的n次方,需要进行n-1次乘法运算。现考虑以2为底,缓存中间结果,从而避免重复计算。例如power(x,4)=power(x,2)*power(x,2),只需两次乘法运算。再将power(x,4)的结果保留,则power(x,8)=power(x,4)power(x,4)……若采用递归算法,以n=0为基准情形(power(x,0)=1),若n为奇数,则返回power(xx, n/2)x,若n为偶数,则返回power(xx, n/2),这样每经过一次递归调用,问题规模减半,预计算法时间复杂度为O(log2n)。同理,若以3为底,以n=0,n=1及n=2为基准情形(power(x,0)=1,power(x,1)=x, power(x,2)=x^2)按n%3为0,1,2分类,每次递归调用问题规模缩小至1/3,预计算法时间复杂度为O(log3n)。
问题描述:大小为N的数组A,其主要元素是一个出现次数超过N/2的元素(从而这样的元素最多有一个)。例如,数组3,3,4,2,4,4,2,4,4有一个主要元素4,而数组3,3,4,2,4,4,2,4没有主要元素。如果没有主要元素,那么你的程序应该指出来。下面是求解该问题的一个算法的概要:
首先,找出主要元素的一个候选元。这个候选元是唯一有可能是主要元素的元素。第二步确定是否该候选元实际上就是主要元素,这正好是对数组的顺序搜索。为找出数组A的一个候选元,构造第二个数组B。比较A1和A2,如果它们相等,则取其中之一加到数组B中;否则什么也不做。然后比较A3和A4,同样地,如果它们相等,则取其中之一加到B中;否则什么也不做。以该方式继续下去直到读完这个数组。然后,递归地寻找B中的候选元;它也是A的候选元。
分治算法:构造第二个数组B。比较A1和A2,如果它们相等,则取其中之一加到数组B中;否则什么也不做。然后比较A3和A4,同样地,如果它们相等,则取其中之一加到B中;否则什么也不做。以该方式继续下去直到读完这个数组。然后对B数组重复上述操作。最后对数组A进行遍历,确定该候选元是否为主元。预计算法时间复杂度为O(n)
非分治算法:采用双重for循环,从A1开始,将数组内的每一个元素依次与所有元素比较,若相同,则count++。只要count>n/2,则该元素为主元,返回该元素。若循环结束还未满足条件,则返回-1,表示没有找到主元。预计算法时间复杂度为O(n2)
#include <stdio.h> #include <stdlib.h> #include<time.h> long int power(int x,int n){ if(n==0){ return 1; } if(n%2==0){ return power(x*x,n/2); } else return power(x*x,n/2)*x; } int main(){ clock_t start_time,end_time; int x=3; start_time=clock(); for(int i = 0;i < 1000000;i++){ power(x,100); } end_time=clock(); printf("%f",(double)(end_time - start_time)); return 0; }
#include <stdio.h> #include <stdlib.h> #include<time.h> long int power(int x,int n){ if(n==0){ return 1; } if(n==1){ return x; } if(n==2){ return x*x; } if(n%3==0){ return (power(x*x*x,n/3)); } if(n%3==1){ return power(x*x*x,n/3)*x; } return power(x*x*x,n/3)*x*x; } int main(){ clock_t start_time,end_time; int x=3; start_time=clock(); for(int i = 0;i < 1000000;i++){ power(x,2000); } end_time=clock(); printf("%f",(double)(end_time - start_time)); return 0; }
3.主元问题
分治算法
#include <stdio.h> #include <stdlib.h> int major(int array[], int n) //找出备选主元 { int i = 0, j = 0, k = n/2, tmp; if(n <= 0) { return -1; } if(1 == n) { return array[0]; } for( ; i < k ; i++) { if(array[2*i] == array[2*i + 1]) { tmp = array[j]; array[j++] = array[2*i]; array[2*i] = tmp; } } tmp = major(array, j); if((n % 2 == 1) && (tmp == -1)) { return array[n-1]; } return tmp; } int main() { int a[10] = {1,2,1,2,1,2,1,2,1,2}; //遍历数组判断备选元是否为主元 int majorele = major(a,10); int count = 0; for(int i = 0; i < 10; i++) { if(a[i] == majorele) { count++; } } if(count <= 5){ printf("无主元\n"); } else { printf("主元为:%d\n", majorele); } return 0; }
附:主元问题迭代代码(时间复杂度为O(n))
#include <stdio.h> #include <stdlib.h> int major(int *array, int n) //找出被选元 { int tmp = -1, count = 0; for(int i = 0; i < n; i++) { if(array[i] == tmp) { count++; } else if (count == 0) { tmp = array[i]; count++; } else count--; } if(count == 0) return -1; return tmp; } int main() { int a[11] = {1,2,1,2,1,2,1,2,1,1}; int majorele = major(a,10); int count = 0; if(majorele == -1) { printf("无主元"); } else //遍历数组判断被选元是否为主元 { for(int i = 0; i < 10; i++) { if(a[i] == majorele) { count++; } } if(count <= 5){ printf("无主元\n"); } else { printf("主元为:%d\n", majorele); } } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。