已知一組數(其中有重複元素),求這組數可以組成的所有子集中,子集中的各個元素和為整數target的子集,結果中無重複的子集。
例如:nums=[10,1,2,7,6,1,5], target=8
結果為:[[1,7],[1,2,5],[2,6],[1,1,6]]
該題無論是回溯法或位運演算法,整體時間複雜度為o(2^n)。
為了減小時間複雜度,在搜尋回溯過程中應進行剪枝操作:
遞迴呼叫時,計算已選擇元素的和sum,若sum>target,不再進行更深的搜尋,直接返回。
#include
#include
class
solution;~
solution()
; std::vectorint>> combinationsum2
(std::vector<
int>
& candidates,
int target)
private
:void
generate
(int i, std::vector<
int>
& nums, std::vectorint>>
& result, std::vector<
int> item,
int sum,
int target)
sum +
= nums[i]
; item.
push_back
(nums[i]);
if(sum==target&&
find
(result.
begin()
,result.
end(
),item)
==result.
end())
generate
(i +
1, nums, result, item, sum, target)
; sum -
= nums[i]
; item.
pop_back()
;generate
(i +
1, nums, result, item, sum, target);}
};intmain()
for(
unsigned
int j =
0; j < result[i]
.size()
; j++
)printf
("\n");
}return0;
}
執行結果為:
[1]
[1][
6][1
][2]
[5][
1][7
][2]
[6]
此處若將原來的數進行逆序排序後再進行剪枝回溯也可以。
只需將
std::
sort
(candidates.
begin()
, candidates.
end())
;
改為
std::
sort
(candidates.
rbegin()
, candidates.
rend()
);
改為逆序後的執行結果為:
[7]
[1][
6][2
][6]
[1][
1][5
][2]
[1]
逆元法求組合數
a b p a p b p a b p a p b p a b p a p b p 但是 a b frac ba p amo dpbm od p frac bmodpa modp 這種時候就要用到逆元 在求組合數時 c nm tbinom mn n m n m frac m n m n p n m ...
Leetcode 組合總數II(回溯法 剪枝)
給定乙個陣列 candidates 和乙個目標數 target 找出 candidates 中所有可以使數字和為 target 的組合。candidates 中的每個數字在每個組合中只能使用一次。說明 所有數字 包括目標數 都是正整數。解集不能包含重複的組合。示例 1 輸入 candidates 1...
C 求組合數 再取模
c n,m n n m m c 在處理大數除法的時候好像會出現問題,所以用除法有時候會因為精度不夠沒法得到正確答案.需要把除法變成乘法.知識儲備 逆元 快速冪 逆元 若a x m 1 我們稱x是a的逆元,x寫做a 1 相當於整除中的倒數 那假設我們要求a b m的值,當b特別大時我們無法得到正確答案...