題目鏈結
給你乙個整數陣列 nums 和乙個整數 k 。你需要將這個陣列劃分到 k 個相同大小的子集中,使得同乙個子集裡面沒有兩個相同的元素。
乙個子集的 不相容性 是該子集裡面最大值和最小值的差。
請你返回將陣列分成 k 個子集後,各子集 不相容性 的 和 的 最小值 ,如果無法分成分成 k 個子集,返回 -1 。
子集的定義是陣列中一些數字的集合,對數字順序沒有要求。
輸入:nums =
[1,2,1,4], k = 2
輸出:4
解釋:最優的分配是 [1,2] 和 [1,4] 。
不相容性和為 (2-1) + (4-1)
= 4 。
注意到 [1,1] 和 [2,4] 可以得到更小的和,但是第乙個集合有 2 個相同的元素,所以不可行。
輸入:nums =
[6,3,8,1,3,1,2,2], k = 4
輸出:6
解釋:最優的子集分配為 [1,2],[2,3],[6,8] 和 [1,3] 。
不相容性和為 (2-1) + (3-2) + (8-6) + (3-1)
= 6 。
輸入:nums =
[5,3,3,6,3,3], k = 3
輸出:-1
解釋:沒辦法將這些數字分配到 3 個子集且滿足每個子集裡沒有相同數字。
比賽時只想到了爆搜,完全忽視了 dp,結果最後也沒搞出來,後來發現這題是狀壓 dp,好像很久沒碰到了?,的確比較難想~
狀壓 dp,顧名思義就是壓縮狀態,暴力判斷的複雜度最大為 16
!16!
16!,而狀壓 dp 的最壞複雜度為 2
162^
216,顯然後者是可取的。我們用乙個二進位制數 x
xx 表示陣列選擇的狀態,對二進位制的每一位,1
11 表示選中,0
00 表示不選,首先可以用 val
ue[x
]value[x]
value[
x]記錄每個合法二進位制數的不相容性,何為合法二進位制數?顯然有且僅有 num
s.si
ze()
k\frac
knums.
size
() 個 1
11,且這些選中的數不重複,即為合法。在算完不相容性後,很容易得到狀態轉移方程,用 dp[
i]
dp[i]
dp[i
] 表示某乙個二進位制狀態的最小不相容性,則有:
d p[
i]=m
in(d
p[i]
,dp[
i⊕j]
+val
ue[j
]),j
⊂i
dp[i]=min(dp[i],dp[i\oplus j]+value[j]),j\subset i
dp[i]=
min(
dp[i
],dp
[i⊕j
]+va
lue[
j]),
j⊂i解釋一下,當 j
jj 為 i
ii 的子集時,i
ii 的最小不相容性即為去掉 j
jj 的狀態(i⊕j
i\oplus j
i⊕j) 的最小不相容性加上狀態 j
jj 的不相容性,最後全選的狀態 m=2
n−
1m=2^n-1
m=2n−1
的 dp[m
]dp[m]
dp[m
] 即為最終答案,ac**如下:
class
solution
int p=0;
for(
int j=
1;j<=n;j++)}
if(!p)}
} dp[0]
=0;for
(int i=
0;i}}
return dp[m-1]
;}};
leetcode 使結果不超過閾值的最小除數
給你乙個整數陣列 nums 和乙個正整數 threshold 你需要選擇乙個正整數作為除數,然後將陣列裡每個數都除以它,並對除法結果求和。請你找出能夠使上述結果小於等於閾值 threshold 的除數中最小的那個。每個數除以除數後都向上取整,比方說 7 3 3 10 2 5 題目保證一定有解 示例 ...
Leetcode 最小K個數
思路 基於快排改進 選取arr 0 作為基準值,tmp arr 0 排序後,返回tmp的下標index 此時,arr index 左側的值都小於tmp,右側的值都大於tmp。如果k index,那麼從起始點0到下標index 1的值就為最小的k個數,如果k index,說明k個數在區間 0,inde...
leetcode 最小高度樹
給定乙個有序整數陣列,元素各不相同且按公升序排列,編寫乙個演算法,建立一棵高度最小的二叉搜尋樹。由於陣列已經是有序陣列,所以構建二叉搜尋樹並不難,基於二叉樹的特性,我們將陣列劃分為兩部分,遞迴構建其左右子樹即可.對於題目中要求的高度最小,我們知道一棵平衡樹是高度最小的二叉樹.因此我們每次切分應當保證...