朋友去面試頭條的前端,二面,第一個題目,就是下面這張紙,面試官也會給一張紙要求手寫答案。若是你看到就馬上知道了怎麼解答,那能夠直接忽略本文了,或者有更好的寫法,直接評論區留言吧,謝謝~前端
個人學習風格老是想着按部就班,下面從幾個小題開始。面試
題目:給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們組成的數組。 你不能重複利用這個數組中一樣的元素。算法
其實就是一個數組,找出兩個元素,他們的和是指定的值,可是不能一直就一個元素,也就是說加數組只有4的話,不能返回結果是[4,4]這樣數組
var nums = [8, 9, 2, 15, 7, 1]
var target = 9
var twoSum = function(nums, target) {
var result = []
for(var i=0; i<nums.length;i++){
for(var j=i+1; j<nums.length;j++){
if(nums[i]+nums[j] === target){
result.push([nums[i],nums[j]])
}
}
}
return result
}
console.log( twoSum(nums, target) )
複製代碼
運行結果以下函數
代碼很簡單,也不用什麼解釋吧。不過要引出來的是下面一種解法,遞歸。學習
var nums = [8, 9, 2, 15, 7, 1]
var target = 9
var twoSum = function(nums, target) {
var result = []
var _sum = function(nums, target){
if(nums.length === 0){
return false
}
for(var i = 1; i < nums.length; i++){
if((nums[0] + nums[i]) === target){
result.push([nums[0] , nums[i]])
}
}
nums.splice(0,1) // 或者使用 nums.shift(),刪除數組第一個元素
return _sum(nums, target)
}
_sum(nums, target)
return result
}
console.log( twoSum(nums, target) )
複製代碼
運行結果以下,固然,和上述結果是同樣的spa
小結 代碼稍微多了一點,其實思想是同樣的,不過想更好的解釋遞歸,那麼須要再把題目簡化一下3d
題目:仍是上面的題目,加上一個限定條件:你能夠假設每種輸入只會對應一個答案。也就是說對應這樣的題幹數組[11, 7, 10, 2] 只有 [7,2]這樣一個結果。對於只有一個結果這樣的狀況,遞歸的寫法代碼會簡練的多。code
var twoSum = function(nums, target) {
// 1
var result = []
if(nums.length === 0){
// 2
return false
}
for(var i = 1; i < nums.length; i++){
if((nums[0] + nums[i]) === target){
result.push([nums[0], nums[i]])
// 3
return result
}
}
// 4
nums.shift()
// 5
return twoSum(nums, target)
}
console.log( twoSum(nums, target) )
複製代碼
小結 :註釋1 中,會把result置爲[], 那豈不是每次遞歸調用這個方法時候,開始都是重置?答,由於前提條件已經改了,咱們返回的結果只有一個 註釋4 ,修改遞歸執行函數的參數,畢竟要每次不同嘛要否則怎麼進行下去。cdn
提問,真的清楚每一個 return 的做用嗎?好比 註釋5 那裏的return不寫的話,有什麼區別?這個必定要清楚。
根據上面例子,很容易想到3重循環,確實也是能夠解決的,只是那個斷定條件,有些low 而且假如是尋找長度爲4子數組呢?那要for循環4次?顯然不可取
提問 ,若是用遞歸,這個問題怎麼解決?
var candidates = [2, 3, 8, 4, 10, 15]
var target = 9
var combinationSum2 = function(candidates, target) {
const buffer = [];
const result = [];
const backTrace = (index, target) => {
if(target == 0) {
return result.push(buffer.slice());
}
if(target < 0) {
return;
}
if(index === candidates.length) return;
buffer.push(candidates[index]);
backTrace(index + 1, target - candidates[index]);
buffer.pop();
backTrace(index + 1, target);
}
backTrace(0, target);
return result.filter(item => item.length === 3)
};
console.log(combinationSum2(candidates, target))
複製代碼
運行結果以下
看到這裏,相信已經明白了這個代碼所作的事情,其實這就是回溯算法,不斷試錯,錯誤的話,回到上個狀態,換參數繼續試錯下去。
其實,最最開始的題目,答案已經有了。由於咱們上面的代碼,最後返回的result中,含有多個和爲目標值的數組,那麼咱們只須要再遍歷一下這個result的每一項,篩選出長度符合要求的便可。