持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
198. 打家劫舍
思路
(动态规划) O(n)
给定一个代表金额的非负整数数组nums,相邻房间不可偷,让我们输出可以偷窃到的最高金额。
样例:
如样例所示,nums = [2,7,9,3,1],偷窃1,3,5号房间可以获得最高金额12,下面来讲解动态规划的做法。
状态表示: f[i]表示偷窃1号到i号房间所能获得的最高金额。那么,f[n]就表示偷窃1号到n号房间所能获得的最高金额,即为答案。
状态计算:
假设有i间房间,考虑最后一间偷还是不偷房间,有两种选择方案:
- 1、偷窃前
i-1间房间,不偷窃最后一间房间,那么问题就转化为了偷窃1号到i - 1号房间所能获得的最高金额,即f[i] = f[i-1]。
- 2、偷窃前
i - 2间房间和最后一间房间 (相邻的房屋不可闯入),那么问题就转化为了偷窃1号到i- 2号房间所能获得的最高金额再加上偷窃第i号房间的金额,即f[i] = f[i - 2] + nums[i]。 (下标均从1开始)
两种方案,选择其中金额最大的一个。因此状态转移方程为: f[i] = max(f[i - 1], f[i - 2] + nums[i])。 (下标均从1开始)
初始化: f[1] = nums[0],偷窃1号房间所能获得的最高金额为nums[0]。
实现细节:
我们定义的状态表示f[]数组和nums[]数组下标均是从1开始的,而题目给出的nums[]数组下标是从0开始的。为了一 一对应,状态转移方程中的nums[i]的值要往前错一位,取nums[i - 1],这点细节希望大家可以注意一下。
时间复杂度分析: O(n),其中 n是数组长度。只需要对数组遍历一次。
c++代码
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
vector<int>f(n + 1);
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];
}
};
338. 比特位计数
思路
(动态规划) O(n)
状态表示: f[i]表示i 的二进制表示中1的个数。
状态计算:
考虑i的奇偶性,有两种不同选择:
i是偶数,则f[i] = f[i/2],因为i/2 * 2本质上是i/2的二进制左移一位,低位补零,所以1的数量不变。i是奇数,则f[i] = f[i - 1] + 1,因为如果i为奇数,那么i - 1必定为偶数,而偶数的二进制最低位一定是0,那么该偶数+1后最低位变为1且不会进位,所以奇数比它上一个偶数二进制表示上多一个1。
初始化: f[0] = 0。
时间复杂度分析: O(n)。
c++代码
class Solution {
public:
vector<int> countBits(int n) {
vector<int> f(n + 1);
f[0] = 0; //初始化
for(int i = 1; i <= n; i++){
if(i & 1) f[i] = f[i - 1] + 1;
else f[i] = f[i >> 1];
}
return f;
}
};
200. 岛屿数量
思路
(深度优先遍历)
- 从任意一个陆地点开始,即可通过四连通的方式,深度优先搜索遍历到所有与之相连的陆地,即遍历完整个岛屿。每次将遍历过的点清
0。 - 重复以上过程,可行起点的数量就是答案。
时间复杂度分析: 由于每个点最多被遍历一次,故时间复杂度为 O(n*m)
空间复杂度分析: 最坏情况下,需要额外O(n*m) 的空间作为系统栈。
c++代码
class Solution {
public:
vector<vector<char>> g;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int numIslands(vector<vector<char>>& grid) {
g = grid;
int cnt = 0;
for(int i = 0; i < g.size(); i++)
for(int j = 0; j < g[i].size(); j++){
if(g[i][j] == '1'){
dfs(i, j);
cnt++;
}
}
return cnt;
}
void dfs(int x, int y){
g[x][y] = '0';
for(int i = 0; i < 4; i++){
int a = x + dx[i], b = y + dy[i];
if(a < 0 || a >= g.size() || b < 0 || b >= g[a].size() || g[a][b] == '0') continue;
dfs(a, b);
}
}
};