【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法
来源:互联网 发布:近几年淘宝销售排行榜 编辑:程序博客网 时间:2024/04/30 06:23
转自http://blog.csdn.net/morewindows/article/details/8439393
【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法
随机生成和为S的N个正整数有很多种解法。下面讲解一种比较高效且比较有趣味性的解法——投影法。
以生成和为20的4个数为例,可以先生成随机生成0到20之间的三个数字再排序,假设得到了4,7,18。然后在X-Y数轴上画出这三个数,如下图:
然后将这些数值投影到Y轴上,可得下图:
由图很容易看出AB,BC,CD,DE这四段的长度和肯定为20。因此AB,BC,CD,DE这四段的长度即和为20的4个数,这4个数分别为4,3,11,2。
这种方法只要随机生成N - 1个小于S的不同数字,排序后计算两两差值就可以得到和为S的N个正整数,因此效率还是比较高的。下面给出完整代码(随机生成N - 1个不同数可以参考《STL系列十一随机三趣题——随机重排,文件中随机取一行,生成N个随机数》):
#include <cstdio>#include <ctime>#include <set>#include <algorithm>using namespace std;//在[s, e)区间上随机取n个数并存放到a[]中void GetRandomNum(int *a, int n, int s, int e){std::set<int> set_a;srand(time(NULL));for (int i = e - n; i < e; i++){int num = (rand() % i) + s;if (set_a.find(num) == set_a.end())set_a.insert(num);elseset_a.insert(i);}i = 0;std::set<int>::iterator pos;for (pos = set_a.begin(); pos != set_a.end(); pos++)a[i++] = *pos;}int main(){const int NSUM = 20;const int NCOUNT = 4;printf(" 生成和为%d的%d个数 \n", NSUM, NCOUNT);printf("--- by MoreWindows( http://blog.csdn.net/MoreWindows ) ---\n\n");int a[NCOUNT];GetRandNumberInRange(a, NCOUNT - 1, 0, NSUM);sort(a, a + NCOUNT - 1);a[NCOUNT - 1] = NSUM;printf(" 已经生成和为%d的%d个数: \n", NSUM, NCOUNT);printf("%d ", a[0]);for (int i = 1; i < NCOUNT; i++)printf("%d ", a[i] - a[i - 1]);putchar('\n');return 0;}
运算结果如下图所示:
这种“投影法”能有效解决随机生成和为S的N个正整数,其算法本质是通过“投影”得到各数据之间的长度差,而且这些长度差之和即投影线段的总长度显然会等于最大数据的值减去最小数据的值。
下面分析下算法的时间复杂度:
算法分为生成随机的N-1个数+排序+遍历共费时O(N * logN) +O(N * logN) + O(N),整体时间复杂度为O(N * logN)。
算法的最主要费时操作在排序上,如果数据量不是太大,使用基数排序(见《【白话经典算法系列之十】一道有趣的GOOGLE面试题解法》)可以将排序操作的时间复杂度降低到O(N)。
其次在生成随机的N-1个数时,虽然只要调用rand()随机函数N-1次,但由于使用了set来做数据存储的容器,因此每次插入数据前的查找要费时O(logN),插入新数据时也要费时O(logN),可以改用hast_set来进一步提高效率(见《STL系列之六 set与hash_set》)。
欢迎大家讨论新颖的解法^_^,多多交流,开阔思路。
- 【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法
- 【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法
- 【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法
- 白话经典算法系列之十三 随机生成和为S的N个正整数——投影法
- 白话经典算法系列之十三 随机生成和为S的N个正整数——投影法
- 白话经典系列之十三 随机生成和为S的N个正整数--投影法
- 随机生成和为S的N个正整数——投影法
- 随机生成和为S的N个正整数——投影法
- 随机生成和为S的N个正整数——投影法
- 随机生成和为S的N个正整数——投影法
- 随机生成和为S的N个正整数——投影法
- 随机生成和为S的N个正整数——投影法
- 随机生成和为S的N个整数——投影法
- 随机生成N个和为S的正整数
- 算法-生成和为S的N个正整数
- 20141008个人日志(空数组添加元素不报错,快速找出不成对出现的元素,随机生成和为S的N个正整数)
- 随机生成和为S的N个数
- 随机生成n个不重复的正整数
- 从尾到头打印链表
- 【OpenCV入门指南】第十一篇 鼠标绘图
- 2014新生暑假个人排位赛01 A. 学姐的桌面
- Windows系统CPU内存网络性能统计第一篇 内存
- A POJ1611
- 【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法
- 2014新生暑假个人排位赛01 B. 学姐去学车
- HDU 2014 青年歌手大奖赛_评委会打分
- android 设置系统屏幕亮度
- 【OpenCV入门指南】第十三篇 人脸检测
- NYOJ 480 Fibonacci Again!
- Android:调节屏幕亮度
- 如何利用OpenCV自带的haar training程序训练分类器
- HDU 2012 素数判定