关于digit统计算法(C语言实现)
2016-08-22 18:00
597 查看
在练习题目的时候,遇到了这个问题:对输入的整数进行digit的处理。具体处理如:统计完全平方数且有至少两个字位相同。
最初的想法是需要一个数组进行存储计算出来的数位,再遍历判断是否有两个相同的数位。
这种做法肯定可行,但是需要考虑,如果是静态设定数组的位数,比如:
那么,想一想,要是恰好是10个digits,那么以上的逻辑就没有问题,但是,要是,只用到了其中的一部分呢?那么没有用到的就是0了,这样判断的时候,0的个数为大于等于2了能算满足吗?
肯定不行!
这样申请的数组必须是恰好是我们得到的数位个数。比如,123,可以得到1,2,3,那么这个数组必须恰好存储三个元素,才能进行下一步判断。
好了,直接看题目(来源于PAT训练题–基础题 :)):
本题要求实现一个函数,判断任一给定整数N是否满足条件:它是完全平方数,又至少有两位数字相同,如144、676等。
函数接口定义:
其中N是用户传入的参数。如果N满足条件,则该函数必须返回1,否则返回0。
裁判测试程序样例:
输入样例:105 500
输出样例:
cnt = 6
我首先想到了一个特别复杂的实现,用的是单链表,动态分配堆空间:
但是这个做法是可以优化的,即:完全不用单链表,因为这个算法的核心在桶,仅需要一个固定的container存储0-9数位即可,那么简化版本是:
总结:第一种解法用来练习结构体的使用是很好的。
这里的两个要点:
如何得到digit
如何用桶收集相关数据
具体代码中已经有详细演示,不再多说。
最初的想法是需要一个数组进行存储计算出来的数位,再遍历判断是否有两个相同的数位。
这种做法肯定可行,但是需要考虑,如果是静态设定数组的位数,比如:
int arr[10]
那么,想一想,要是恰好是10个digits,那么以上的逻辑就没有问题,但是,要是,只用到了其中的一部分呢?那么没有用到的就是0了,这样判断的时候,0的个数为大于等于2了能算满足吗?
肯定不行!
这样申请的数组必须是恰好是我们得到的数位个数。比如,123,可以得到1,2,3,那么这个数组必须恰好存储三个元素,才能进行下一步判断。
好了,直接看题目(来源于PAT训练题–基础题 :)):
本题要求实现一个函数,判断任一给定整数N是否满足条件:它是完全平方数,又至少有两位数字相同,如144、676等。
函数接口定义:
int IsTheNumber ( const int N );
其中N是用户传入的参数。如果N满足条件,则该函数必须返回1,否则返回0。
裁判测试程序样例:
#include<stdio.h> #include <math.h> int IsTheNumber ( const int N ); int main() { int n1, n2, i, cnt; scanf("%d %d", &n1, &n2); cnt = 0; for ( i=n1; i<=n2; i++ ) { if ( IsTheNumber(i) ) cnt++; } printf("cnt = %d\n", cnt); return 0; } /* 你的代码将被嵌在这里 */
输入样例:105 500
输出样例:
cnt = 6
我首先想到了一个特别复杂的实现,用的是单链表,动态分配堆空间:
#include<stdio.h> #include<math.h> #include<stdlib.h> ///time:2016-8-22 //定义数组结点 typedef struct Node{ //Node是结构体的名字 int data; struct Node* next; } INode,*INodeList;//声明数据类型名 int IsTheNumber(const int N){ int n = N; int result = 0; //no.1 : is n*n type //no.2 : split digits, at least two are the same double root = sqrt(N); int ce = ceil(root); int fl = floor(root); //如果上取整和下取整相同,则是个完全平方数,否则就不是,直接令result为0 if(ce != fl){ result = 0; } else{ //分配新数组,L作为头结点,用头结点的data值存储结点个数 INodeList L = (INodeList)malloc(sizeof(INode)); L->next = NULL; L->data = 0; //头插法建立单链表 while(n != 0){ INodeList p = (INodeList)malloc(sizeof(INode)); p->data = n % 10; p->next = L->next; L->next = p; n /= 10; L->data = L->data+1;//结点个数加1 } //因为每一个元素都是0-9,所以可以采用水桶法,共需要十个桶 int container[10]; for(int i = 0; i < 10; i++){ container[i] = 0;//初始化为0 } INodeList q = L->next; //检查桶里面搜集的元素 while(q != NULL){ container[q->data]++; q = q->next; } //遍历桶,如果有桶的元素大于等于2则返回true for(int i = 0; i < 10; i++){ if(container[i] >= 2){ result = 1; } } } return result; } int main() { int n1, n2, i, cnt; scanf("%d %d", &n1, &n2); cnt = 0; for ( i=n1; i<=n2; i++ ) { if ( IsTheNumber(i) ) cnt++; } printf("cnt = %d\n", cnt); return 0; }
但是这个做法是可以优化的,即:完全不用单链表,因为这个算法的核心在桶,仅需要一个固定的container存储0-9数位即可,那么简化版本是:
int IsTheNumber(const int N){ int n = N; int result = 0; //no.1 : is n*n type //no.2 : split digits, at least two are the same double root = sqrt(N); int ce = ceil(root); int fl = floor(root); if(ce != fl){ result = 0; } else{ //因为每一个元素都是0-9,所以可以采用水桶法,共需要十个桶 int container[10]; for(int i = 0; i < 10; i++){ container[i] = 0;//初始化为0 } while(n != 0){ container[n % 10]++; n /= 10; } //遍历桶,如果有桶的元素大于等于2则返回true for(int i = 0; i < 10; i++){ if(container[i] >= 2){ result = 1; } } } return result; }
总结:第一种解法用来练习结构体的使用是很好的。
这里的两个要点:
如何得到digit
如何用桶收集相关数据
具体代码中已经有详细演示,不再多说。
相关文章推荐
- 有关统计单词频率的算法c语言实现
- 蓝桥杯 - 算法训练 字串统计 C语言实现
- 关于统计变换(CT/MCT/RMCT)算法的学习和实现
- 有关统计单词频率的算法c语言实现
- 关于傅里叶变换的理解、快速傅里叶算法的推导以及蝶形运算的c语言实现
- 有关统计单词频率的算法c语言实现
- 有关统计单词频率的算法c语言实现
- 关于统计变换(CT/MCT/RMCT)算法的学习和实现,也称为局部二进制模式(LBP)
- 算法导论——关于快速排序的实现(c语言实现)
- 关于欧几里得及其扩展算法(C语言实现)
- 关于统计变换(CT/MCT/RMCT)算法的学习和实现
- 初入C语言!整数算法练习1:通过编程实现,统计1~n有多少个9 ? 提示:n通过参数传入!
- 关于统计变换(CT/MCT/RMCT)算法的学习和实现
- 关于统计变换(CT/MCT/RMCT)算法的学习和实现
- 关于用C语言来实现对一个文档中的条目数字进行统计排序的实现
- 关于RSA硬件算法的实现问题!
- 10个重要的算法C语言实现源代码:拉格朗日,牛顿插值,高斯,龙贝格,牛顿迭代,牛顿-科特斯,雅克比,秦九昭,幂法,高斯塞德尔
- 10个重要的算法C语言实现源代码:拉格朗日,牛顿插值,高斯,龙贝格,牛顿迭代,牛顿-科特斯,雅克比,秦九昭,幂法,高斯塞德尔
- 10个重要的算法C语言实现源代码
- C语言中实现点在多边形内的算法