打家劫舍II

题目描述(LeetCode)

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

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

示例 1:

输入: [2,3,2]
输出: 3
解释: 你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

示例 2:

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

 

题目讲解

打家劫舍 II 和 打家劫舍 相比,题目只有一个变化。
这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。
这个规则会带来怎样的影响呢?
如果按照原来的解法,最要命的问题就是无法确定是否即抢了第一家又抢了最后一家。
那么,要怎么保证抢了第一家就不抢最后一家呢?

 

对于上面我们可以采取拆解的方式,变为两个打家劫舍I的方式,如下:

相比于第一题,此题目将首位也作为相邻,假设总共有N个房子,思路是:
1.分两次求解,首先是第一家到第N-1家,求得偷得最多的值,记Max01;
2.之后再次求得第2家到第N家可以偷的最大值,记为Max02;
3.最后比较Max01与Max02,将最大的那个值返回。

 

题目代码

对于上面的逻辑,用swift代码如下:

import UIKit

let numsArray: [Int] = [1,2,3,1]
func robs(numsArr: [Int]) -> Int {
    if numsArr.count == 0 {
        return 0
    }
    if numsArr.count == 1 {
        return numsArr[0]
    }
    if numsArr.count == 2 {
        if numsArr[0] < numsArr[1] {
            return numsArr[1]
        } else {
            return numsArr[0]
        }
    }
    var dp1 = [Int]()
    var dp2 = [Int]()
    /**
     *偷第一家与不偷第一家
     */
    
    //偷第一家
    for i in 0..<numsArr.count - 1 {
        if i < 2 {
            dp1.append(numsArr[0])
            if dp1[0] < numsArr[1] {
                dp1.append(numsArr[1])
            } else {
                dp1.append(dp1[0])
            }
        } else {
            let fk_1 = dp1[i - 1]
            let fk_2 = dp1[i - 2] + numsArr[i - 1]
            let temp = fk_1 > fk_2 ? fk_1 : fk_2
            dp1.append(temp)
        }
    }
    
    //不偷第一家,可以偷最后一家
    for i in 1..<numsArr.count {
        if i < 3 {
            dp2.append(numsArr[1])
            if dp2[0] < numsArr[2] {
                dp2.append(numsArr[2])
            } else {
                dp2.append(dp2[0])
            }
        } else {
            let fk_1 = dp2[i - 1]
            let fk_2 = dp2[i - 2] + numsArr[i]
            let temp = fk_1 > fk_2 ? fk_1 : fk_2
            dp2.append(temp)
        }
    }
    
    //比较大小
    let maxRobs = dp1[dp1.count - 1] > dp2[dp2.count - 1] ? dp1[dp1.count - 1] : dp2[dp2.count - 1]
    return maxRobs
}

let maxRobs = robs(numsArr: numsArray)
print(maxRobs)

通过playground打印出结果如下:

打家劫舍II

 直接拷贝上面代码即可!

 

上面就是打家劫舍II的版本,希望对大家理解有所帮助,看完麻烦点个赞呗,谢谢!

上一篇:The Number of Products


下一篇:P1091-合唱队形