一、題目
描述給定整數a1、a2、…an,判斷是否可以從中選出若干數,使它們的和恰好為k。
輸入首先,n和k,n表示數的個數,k表示數的和。
接著一行n個數。
(1<=n<=20,保證不超int範圍)
輸出如果和恰好可以為k,輸出「yes」,並按輸入順序依次輸出是由哪幾個數的和組成,否則「no」
樣例輸入
4 13
1 2 4 7
樣例輸出
yes2 4 7
二、實現思路及其**
思路一:dfs深度優先搜尋
(1)初始狀態:對於和k,看是否能從全部元素中找到一種組合使之和等於k;
(2)平行狀態:對當前元素選擇要或者不要,進入下一狀態;
(3)下一狀態:設上一平行狀態已選擇ai元素,則需要對剩下的元素判斷是否能找到一種組合使之和等於k-ai;
(4)若上一平行狀態未選擇ai元素,則需要對剩下的元素判斷是否能找到一種組合使之和等於k;
…………
(5) 若一條支路走不通(k < 0)或者一條支路搜尋到底了(i == arr.length),則需回溯;
(6)yes的判斷:當k 等於 0時,說明已得出一種有效組合使之和==k,按格式輸出該組合即可。
/**
* 深度優先搜尋
* @param arr 陣列
* @param k 和
* @param current 當前判斷元素
*/static arraylist list = new arraylist<
>()
; public static
void
dfs(
int[
] arr,
int k,
int current)
system.
exit(0
);//直接退出程式,避免return到上一平行狀態
}// 走到葉子結點||這條支路走不通,則return到上一平行狀態
if(current == arr.length|| k <0)
return
;// 不要當前元素
dfs(arr,k,current+1)
;// 要當前元素
list.
add(arr[current]);
dfs(arr,k - arr[current]
,current+1)
; list.
remove
(list.
size()
-1);
//回溯,注意index
}
no的判斷:若dfs徹底走完了,list還是為空的話,說明沒有符合的組合,列印「no」。在main()中判斷。
public static
void
main
(string[
] args)
dfs(arr,k,0)
;if(list.
size()
==0) system.out.
println
("no");
// binarysystemsolve(arr,k);
}
思路二:子集二進位制迭代法——最優解法
(1)窮舉子集,當子集和==k時得解。
(2)這裡不需要連續的元素相加,實質是元素組合。模式匹配》想到求非空子集。
/**
* 子集二進位制迭代法
* @param arr
*/public static
void
binarysystemsolve
(int
arr,
int k)
}// (2)計算子集內的和?=k
int sum =0;
for(integer e : set)
if(sum == k)
return;}
}// 2、若遍歷完了所有子集情況,仍找不到==k的組合,列印「no」
system.out.
println
("no");
}
演算法 求二進位制的和
最近面試滴滴的前端,面試官問了一道演算法題,是求兩個二進位制的和,讓我 5 分鐘之內寫出來,當時心機,想到的思路是將兩個二進位制轉化為 10 進製,相加之後得到的值再轉換為二進位制 function changeten params console.log total.tostring 2 chan...
二進位制和三進製的妙用
在it公司的筆試和面試中,總會出現那某些與進製有關的題目,現將一些常出現的進製用法 如下 先來思考幾個問題,並不難,各位大牛應能秒殺 1.小明是個賣蘋果的,小紅一次在小明那買n n 1024 個蘋果。小明每次都要數n個蘋果給小紅,唉,太麻煩了。於是小明想出了一種方法 他把蘋果分在10個袋子中,則無論...
二進位制數 位和位元組
書寫數字的常用方法是十進位制。例如 2157的千位是2,百位是1,十位是5,個位是7,這意味著可以將2157看作如下形式 2 1000 1 100 5 10 7 1 也就是如下形式 2 103 1 102 5 101 7 100 姑且認為,十進位制得以發展的原因是我們都有10根手指。在某種意義上說,...