补充题2 圆环回原点问题
据说是字节面试常考。状态转移的思维有点像爬楼梯,但是要加上步数这个维度。设dp[i][j]为到i点走j步的方案数量,状态转移为dp[i][j] = dp[(i - 1 + 10) % 10][j - 1] + dp[(i + 1) % 10][j - 1],注意防止越界所做的取余处理。
int solution(int n){
if(n <= 1) return 0;
vector<vector<int>> dp(10, vector<int>(n + 1));
dp[0][0] = 1;
for(int j = 1; j <= n; ++j){
for(int i = 0; i < 10; ++i){
dp[i][j] = dp[(i - 1 + 10) % 10][j - 1] + dp[(i + 1) % 10][j - 1];
}
}
return dp[0][n];
}
代码很简短,需要额外注意的是遍历顺序。从状态转移方程可以看出,每个点依赖于前一列的两个值,因此内层循环遍历的必须是列,即点的位置。
其实如果n不很大,16、17左右的话,递归暴搜也可以,每个位置就是选择顺时针走还是逆时针走,递归暴搜时间复杂度是。但是面试的话肯定会让你优化。
void dfs(int pos, int steps, int n, int& ans){
if(steps == n){
if(pos == 0) ++ans;
return;
}
dfs(pos + 1, steps + 1, n, ans);
dfs(pos - 1, steps + 1, n, ans);
}
int solution1(int n){
int ans = 0;
dfs(0, 0, n, ans);
return ans;
}
这两天老师开始催之前一个论文审稿意见的回复和修改,白天实习,晚上回了公寓改论文,抽空刷题,有点难顶。