【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法

原创 2013年01月04日 13:46:21

【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法 

    随机生成和为SN个正整数有很多种解法。下面讲解一种比较高效且比较有趣味性的解法——投影法。

    以生成和为204个数为例,可以先生成随机生成020之间的三个数字再排序,假设得到了4718。然后在X-Y数轴上画出这三个数,如下图:

然后将这些数值投影到Y轴上,可得下图:

由图很容易看出ABBCCDDE这四段的长度和肯定为20。因此ABBCCDDE这四段的长度即和为204个数,这4个数分别为43112

 

这种方法只要随机生成N - 1个小于S的不同数字,排序后计算两两差值就可以得到和为SN个正整数,因此效率还是比较高的。下面给出完整代码(随机生成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);
		else
			set_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;
}

运算结果如下图所示:

 

这种“投影法”能有效解决随机生成和为SN个正整数,其算法本质是通过“投影”得到各数据之间的长度差,而且这些长度差之和即投影线段的总长度显然会等于最大数据的值减去最小数据的值

 

下面分析下算法的时间复杂度:

算法分为生成随机的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系列之六 sethash_set》)。

 

欢迎大家讨论新颖的解法^_^,多多交流,开阔思路。

 

 

《白话经典算法系列》专栏地址:http://blog.csdn.net/morewindows/article/category/859207

转载请标明出处,原文地址:

欢迎关注微博:http://weibo.com/MoreWindows


 

版权声明:本文为博主原创文章,未经博主允许不得转载。

java中实例化Class类对象的三种方式

第一种、通过forName();

Java集合框架:WeakHashMap

  WeakHashMap实现了Map接口,是HashMap的一种实现,它比HashMap多了一个引用队列: ``` private final ReferenceQueue qu...

【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法

随机生成和为S的N个正整数有很多种解法。下面讲解一种比较高效且比较有趣味性的解法——投影法。     以生成和为20的4个数为例,可以先生成随机生成0到20之间的三个数字再排序,假设得到了4,7...
  • suifcd
  • suifcd
  • 2014年10月12日 22:37
  • 402

白话经典算法系列之十三 随机生成和为S的N个正整数——投影法

随机生成和为S的N个正整数有很多种解法。下面讲解一种比较高效且比较有趣味性的解法——投影法。 以生成和为20的4个数为例,可以先生成随机生成0到20之间的三个数字再排序,假设得到了4,7,18。然后...

随机生成和为S的N个正整数——投影法

地址:http://blog.csdn.net/morewindows/article/category/859207      随机生成和为S的N个正整数有很多种解法。下面讲解一种比较高效且比...

【BAT经典算法面试题系列】求和为n的连续正整数

马上就要到9月份了,意味着一年一度的秋招就要开始了,相信不论是正在实习的童鞋还是马上就要找工作的童鞋,BAT无疑是国内的“明星企业”,是每个学计算机的小伙伴们心之向往的企业,但是呢?对于进BAT来讲,...
  • htq__
  • htq__
  • 2016年08月12日 11:11
  • 2458

20141008个人日志(空数组添加元素不报错,快速找出不成对出现的元素,随机生成和为S的N个正整数)

xiangmushang  NSMutableArray *array = [NSMutableArray alloc];     array = nil;     [array ad...
  • sql340
  • sql340
  • 2014年10月09日 16:53
  • 474

贪婪算法--去掉 n 位正整数中的 s 位

键盘输入一个高精度的正整数 n,去掉其中任意 s 个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的n 和 s,寻找一种方案使得剩下的数字组成的新数最小。 怎么样根据贪婪策略删除数字...

第二次编程作业:判断一个正整数是否为质数的算法和 随机生成一个n bit位的长整数

2.1: 判断一个正整数是否为质数的算法。函数签名如下      int isPrime(long a)     输入:一个长整数a     输出:返回1(为质数),返回0(非质数)...

白话经典算法系列之五 归并排序的实现

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法
举报原因:
原因补充:

(最多只允许输入30个字)