分類: 白話經典演算法系列
windows程式設計
2013-01-04 13:46
2459人閱讀收藏
舉報白話經典演算法
和為s的n個正整數
投影法隨機三趣題
【白話經典演算法系列之十三】隨機生成和為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的n個正整數,因此效率還是比較高的。下面給出完整**(隨機生成n - 1個不同數可以參考《
stl系列十一隨機三趣題——隨機重排,檔案中隨機取一行,生成n個隨機數
》):
[cpp]view plain
copy
#include
#include
#include
#include
using
namespace
std;
//在[s, e)區間上隨機取n個數並存放到a中
void
getrandomnum(
int*a,
intn,
ints,
inte)
i = 0;
std::set
>::iterator pos;
for(pos = set_a.begin(); pos != set_a.end(); pos++)
a[i++] = *pos;
} int
main()
運算結果如下圖所示:
這種「投影法」能有效解決隨機生成和為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個正整數 投影法
以生成和為20的4個數為例,可以先生成隨機生成0到20之間的三個數字再排序,假設得到了4,7,18。然後在x y數軸上畫出這三個數,如下圖 然後將這些數值投影到y軸上,可得下圖 由圖很容易看出ab,bc,cd,de這四段的長度和肯定為20。因此ab,bc,cd,de這四段的長度即和為20的4個數,這...
演算法 生成和為S的N個正整數
白話經典演算法系列之十三 隨機生成和為s的n個正整數 投影法 隨機生成和為s的n個正整數有很多種解法。下面講解一種比較高效且比較有趣味性的解法 投影法。以生成和為20的4個數為例,可以先生成隨機生成0到20之間的三個數字再排序,假設得到了4,7,18。然後在x y數軸上畫出這三個數,如下圖 然後將這...
和為s的正整數序列
from typing import list deffindcontinuoussequence target int list list int i 1 滑動視窗的左邊界 j 1 滑動視窗的右邊界 sum 0 滑動視窗中數字的和 res while i target 2 ifsum target...