comments | difficulty | edit_url | tags | ||
---|---|---|---|---|---|
true |
中等 |
|
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 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 。
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 400
我们设计一个函数
函数
- 如果
$i \ge \textit{len}(\textit{nums})$ ,表示所有房屋都被考虑过了,直接返回$0$ ; - 否则,考虑偷窃第
$i$ 间房屋,那么$\textit{dfs}(i) = \textit{nums}[i] + \textit{dfs}(i+2)$ ;不偷窃第$i$ 间房屋,那么$\textit{dfs}(i) = \textit{dfs}(i+1)$ 。 - 返回
$\max(\textit{nums}[i] + \textit{dfs}(i+2), \textit{dfs}(i+1))$ 。
为了避免重复计算,我们使用记忆化搜索的方法,将
时间复杂度
class Solution:
def rob(self, nums: List[int]) -> int:
@cache
def dfs(i: int) -> int:
if i >= len(nums):
return 0
return max(nums[i] + dfs(i + 2), dfs(i + 1))
return dfs(0)
class Solution {
private Integer[] f;
private int[] nums;
public int rob(int[] nums) {
this.nums = nums;
f = new Integer[nums.length];
return dfs(0);
}
private int dfs(int i) {
if (i >= nums.length) {
return 0;
}
if (f[i] == null) {
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
}
return f[i];
}
}
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
int f[n];
memset(f, -1, sizeof(f));
auto dfs = [&](this auto&& dfs, int i) -> int {
if (i >= n) {
return 0;
}
if (f[i] < 0) {
f[i] = max(nums[i] + dfs(i + 2), dfs(i + 1));
}
return f[i];
};
return dfs(0);
}
};
func rob(nums []int) int {
n := len(nums)
f := make([]int, n)
for i := range f {
f[i] = -1
}
var dfs func(int) int
dfs = func(i int) int {
if i >= n {
return 0
}
if f[i] < 0 {
f[i] = max(nums[i]+dfs(i+2), dfs(i+1))
}
return f[i]
}
return dfs(0)
}
function rob(nums: number[]): number {
const n = nums.length;
const f: number[] = Array(n).fill(-1);
const dfs = (i: number): number => {
if (i >= n) {
return 0;
}
if (f[i] < 0) {
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
}
return f[i];
};
return dfs(0);
}
impl Solution {
pub fn rob(nums: Vec<i32>) -> i32 {
fn dfs(i: usize, nums: &Vec<i32>, f: &mut Vec<i32>) -> i32 {
if i >= nums.len() {
return 0;
}
if f[i] < 0 {
f[i] = (nums[i] + dfs(i + 2, nums, f)).max(dfs(i + 1, nums, f));
}
f[i]
}
let n = nums.len();
let mut f = vec![-1; n];
dfs(0, &nums, &mut f)
}
}
function rob(nums) {
const n = nums.length;
const f = Array(n).fill(-1);
const dfs = i => {
if (i >= n) {
return 0;
}
if (f[i] < 0) {
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
}
return f[i];
};
return dfs(0);
}
我们定义
考虑
- 不偷窃第
$i$ 间房屋,偷窃总金额为$f[i-1]$ ; - 偷窃第
$i$ 间房屋,偷窃总金额为$f[i-2]+nums[i-1]$ ;
因此,我们可以得到状态转移方程:
最终的答案即为
时间复杂度
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
f = [0] * (n + 1)
f[1] = nums[0]
for i in range(2, n + 1):
f[i] = max(f[i - 1], f[i - 2] + nums[i - 1])
return f[n]
class Solution {
public int rob(int[] nums) {
int n = nums.length;
int[] f = new int[n + 1];
f[1] = nums[0];
for (int i = 2; i <= n; ++i) {
f[i] = Math.max(f[i - 1], f[i - 2] + nums[i - 1]);
}
return f[n];
}
}
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
int f[n + 1];
memset(f, 0, sizeof(f));
f[1] = nums[0];
for (int i = 2; i <= n; ++i) {
f[i] = max(f[i - 1], f[i - 2] + nums[i - 1]);
}
return f[n];
}
};
func rob(nums []int) int {
n := len(nums)
f := make([]int, n+1)
f[1] = nums[0]
for i := 2; i <= n; i++ {
f[i] = max(f[i-1], f[i-2]+nums[i-1])
}
return f[n]
}
function rob(nums: number[]): number {
const n = nums.length;
const f: number[] = Array(n + 1).fill(0);
f[1] = nums[0];
for (let i = 2; i <= n; ++i) {
f[i] = Math.max(f[i - 1], f[i - 2] + nums[i - 1]);
}
return f[n];
}
impl Solution {
pub fn rob(nums: Vec<i32>) -> i32 {
let n = nums.len();
let mut f = vec![0; n + 1];
f[1] = nums[0];
for i in 2..=n {
f[i] = f[i - 1].max(f[i - 2] + nums[i - 1]);
}
f[n]
}
}
function rob(nums) {
const n = nums.length;
const f = Array(n + 1).fill(0);
f[1] = nums[0];
for (let i = 2; i <= n; ++i) {
f[i] = Math.max(f[i - 1], f[i - 2] + nums[i - 1]);
}
return f[n];
}
我们注意到,当
class Solution:
def rob(self, nums: List[int]) -> int:
f = g = 0
for x in nums:
f, g = max(f, g), f + x
return max(f, g)
class Solution {
public int rob(int[] nums) {
int f = 0, g = 0;
for (int x : nums) {
int ff = Math.max(f, g);
g = f + x;
f = ff;
}
return Math.max(f, g);
}
}
class Solution {
public:
int rob(vector<int>& nums) {
int f = 0, g = 0;
for (int& x : nums) {
int ff = max(f, g);
g = f + x;
f = ff;
}
return max(f, g);
}
};
func rob(nums []int) int {
f, g := 0, 0
for _, x := range nums {
f, g = max(f, g), f+x
}
return max(f, g)
}
function rob(nums: number[]): number {
let [f, g] = [0, 0];
for (const x of nums) {
[f, g] = [Math.max(f, g), f + x];
}
return Math.max(f, g);
}
impl Solution {
pub fn rob(nums: Vec<i32>) -> i32 {
let mut f = [0, 0];
for x in nums {
f = [f[0].max(f[1]), f[0] + x];
}
f[0].max(f[1])
}
}
function rob(nums) {
let [f, g] = [0, 0];
for (const x of nums) {
[f, g] = [Math.max(f, g), f + x];
}
return Math.max(f, g);
}