leetcode 打家劫舍

98 阅读2分钟

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

 

示例 1:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4

示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12

提示:

  • 0 <= nums.length <= 100
  • 0 <= nums[i] <= 400

我想到先进行排序,然后从大到小进行累加,结果是不正确的,因为通过这种方式得到的和不一定是最大的。

/**
 * @param {number[]} nums
 * @return {number}
 */
var rob = function (nums) {
  let len = nums.length;
  if (len < 1) {
    return 0;
  }
  let objArr = [],
    sum = 0,
    sign = -1;
  for (let i = 0; i < len; i++) {
    objArr[i] = { index: i, value: nums[i] };
  }
  objArr.sort((a, b) => b.value - a.value);
  sum += objArr[0].value || 0;
  sign = {
    [objArr[0].index + 1]: true,
    [objArr[0].index - 1]: true,
  };
  for (let j = 1; j < len; j++) {
    let currentIndex = objArr[j].index;
    if (!sign[currentIndex]) {
      sum += objArr[j].value;
      Object.assign(sign, {
        [currentIndex + 1]: true,
        [currentIndex - 1]: true,
      });
    }
  }
  return sum;
};

我打算再思考思考。

经过思考我发现所有的情况是这样的(其实是错误的):

基于这个思考我实现了代码(错误的):

var rob = function (nums) {
  const arr = [0];
  for (let i = -2; i < nums.length; i += 2) {
    const add2 = nums[i + 2] || 0;
    const add3 = nums[i + 3] || 0;
    arr.push(arr[0] + add3);
    arr[0] += add2;
    for (let j = 1; j < arr.length - 1; j++) {
      arr[j] += add3;
    }
  }
  return Math.max(...arr);
};

真实情况是,还有下面的情况:

这种情况下的次数明显比前面的多,并且要考虑的也有很多,所以暂时没有写出对应的代码。因为我觉得肯定有更合理的方式,只不过我仍然会将其实现出来,都说不花笨功夫,当真正容易的方法到来的时候才能真正的领会到,如果真的有一个问题只能这样解决,由于长期养成了使用高明的方法,但对笨方法却很容易头昏,就像现在的我,一向追求方法的我,当遇到这种题的时候发现头很大。


来源:力扣(LeetCode)