20230711-CodeTop

206 阅读1分钟

补充题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左右的话,递归暴搜也可以,每个位置就是选择顺时针走还是逆时针走,递归暴搜时间复杂度是O(2n)O(2^n)。但是面试的话肯定会让你优化。

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;  
}

这两天老师开始催之前一个论文审稿意见的回复和修改,白天实习,晚上回了公寓改论文,抽空刷题,有点难顶。