题目

最近在LeetCode上看到这么一道链接题目

给定一个由正整数组成的数组C和一个目标数字T,查找C中所有的唯一组合,其中候选数字总和为T

C中抽出的数字可以无限重复。

来个例子: 数组[2, 3, 6, 7] 和 目标 7 [2,4,5,8]

需要返回

[
  [7],
  [2, 2, 3]
]

解答

看完题目一开始想的是把7%2,如果余0或者有与余数相等的值做为一个解。如 7%2=1, 2 + 1 = 3 --> [2, 2, 3], 但是一碰到 数组[2, 4, 5] 和 目标 8的情况解歇菜了。
后面又想到了一种方式,一直累减:x_x
图片描述

标准答案

深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。沿着一个方向如果有未搜索的节点就一直搜索下去。

深度优先的主要思想就是“不撞南墙不回头”,“一条路走到黑”,如果遇到“墙”或者“无路可走”时再去走下一条路。

就像下图,按照优先级为右下左上顺时针的方式尝试移动,先往右走,但是有堵墙走不了,所以尝试往下走,如果发现右下左上全都走不了了,就返回到上一个节点进行移动如3 -> 4, 25 -> 26 就是返回到上一个节点。 所以 递归没得跑了。

图片描述

在代码实现上也有标准的模板:

void dfs()  
{  
     // 判断是否到达终点
     if() {
         return;
     }
 
     // 尝试每一个可走方向(右下左上) 
     for(i=0; i<n; i++){ 
         // 判断是否可走,可走调用递归尝试下一步,不可走则尝试该点的其他方向
         if () {
             // 继续下一步  
             dfs();  
         }
     }
}

然后再把我们题目往模板里面一套

var combinationSum = function(candidates, target) {
  let result = []
  let temp = []
  dfs(0, 0, temp)
  return result

  function dfs(value, index, temp) {
    // 判断累加和是否为target 或者 超出了 target
    if (value === target) {
      // 如果和为target就把当前的数组记录下来保存
      result.push(temp.concat())
      return
    } else if (value > target) {
      return
    } else {
      for (let i = index, len = arr.length; i < len; i++) {
        // 记录下之前累加的数字
        let newtemp = temp.concat(arr[i])
        // 继续下一步  
        dfs(value + arr[i], i, newtemp)
      }
    }
  }
}

LeetCode上还有性能更加好的解法,大家可以自己去观摩一番,提高一下姿势水平。

因发明“深度优先搜索算法”,约翰·霍普克洛夫特与罗伯特·塔扬共同获得计算机领域的最高奖:图灵奖。

做完这题最大的感受就是,智商不够,套路来凑,得把基础的数据结构和算法知识看熟啰。

ass♂we♂can


发条橙子
399 声望14 粉丝

我爱吃西瓜