Leetcode 每日一题和每日一题的下一题刷题笔记 27/30

129 阅读3分钟

Leetcode 每日一题和每日一题的下一题刷题笔记 27/30

写在前面

这是我参与更文挑战的第27天,活动详情查看:更文挑战

快要毕业了,才发现自己被面试里的算法题吊起来锤。没办法只能以零基础的身份和同窗们共同加入了力扣刷题大军。我的同学们都非常厉害,他们平时只是谦虚,口头上说着自己不会,而我是真的不会。。。乘掘金鼓励新人每天写博客,我也凑个热闹,记录一下每天刷的前两道题,这两道题我精做。我打算每天刷五道题,其他的题目嘛,也只能强行背套路了,就不发在博客里了。

本人真的只是一个菜鸡,解题思路什么的就不要从我这里参考了,编码习惯也需要改进,各位如果想找刷题高手请教问题我觉得去找 宫水三叶的刷题日记 这位大佬比较好。我在把题目做出来之前尽量不去看题解,以免和大佬的内容撞车。

另外我也希望有得闲的大佬提供一些更高明的解题思路给我,欢迎讨论哈!

好了废话不多说开始第二十七天的前两道题吧!

2021.6.27 每日一题

909. 蛇梯棋

简单来说就是棋盘上有传送门,当走到传送门起点的时候可以传送过去,但只能传一次。这种题还是可以 A*,但是昨天的经历告诉我这里面水太深我把握不住,我还是老老实实 BFS 好一点。。。

去年崩坏三夏活好像就是一个类似这种题的大富翁扔色子棋,屁股后头还有个怪在追自己,还不能让它追上,自己还得把前面的怪排掉,自己还能扔炸弹,那个比这个的变数要多好多,当然和童年桌游比起来还是小巫见大巫。

BFS 的话将节点编号和到达该节点的最少次数作为状态,然后用现在的这个节点之后可能的 6 个步数(也就是下一次)更新后面六个节点的最小次数。因为棋盘是二维的,但是扔色子往前走只能是一维的增加,所以其实暗藏一步把棋盘的编号拉成一维的操作。假设原来的编号是 pxy,现在新的编号是 qx,这两者的关系是

py=qx1Npx={qx1 mod N,py is evenN1(qx1 mod N),py is odd \texttt{p}_y = \lfloor \frac{\texttt{q}_x - 1}{N} \rfloor \\ \texttt{p}_x = {\left \{ \begin{array}{ll} \texttt{q}_x - 1 \ mod \ N, & \texttt{p}_y \ is \ even \\ N - 1 - \left ( \texttt{q}_x - 1 \ mod \ N \right ), & \texttt{p}_y \ is \ odd \\ \end{array} \right.}

有人会疑惑为什么还要两种编号的转化,反正就是顺着下来走完就完事了。主要是输入里面那些传送门是二维坐标,我这里只能保留这么一步,因为我也不知道棋盘上是传送门格子多还是普通格子多,全转化了一了百了。

写代码,代码里在表示队列的时候会用掉 p 和 q,所以点的坐标不用这两个字母,用 rol 和 col 的 r 和 c 表示,一维编号就是 id。


class Solution {
    pair<int, int> id2rc(int id, int n) {
        int r = (id - 1) / n, c = (id - 1) % n;
        if (r % 2 == 1) {
            c = n - 1 - c;
        }
        return {n - 1 - r, c};
    }

public:
    int snakesAndLadders(vector<vector<int>> &board) {
        int n = board.size();
        vector<int> vis(n * n + 1);
        queue<pair<int, int>> q;
        q.emplace(1, 0);
        while (!q.empty()) {
            auto p = q.front();
            q.pop();
            for (int i = 1; i <= 6; i++) {
                int nxt = p.first + i;
                if (nxt > n * n) {
                    break;
                }
                auto rc = id2rc(nxt, n);
                if (board[rc.first][rc.second] > 0) {
                    nxt = board[rc.first][rc.second];
                }
                if (nxt == n * n) {
                    return p.second + 1;
                }
                if (!vis[nxt]) {
                    vis[nxt] = true;
                    q.emplace(nxt, p.second + 1);
                }
            }
        }
        return -1;
    }
};

image.png

2021.6.27 每日一题下面的题

412. Fizz Buzz 写

简单题不说了。


class Solution {
public:
    vector<string> fizzBuzz(int n) {
        vector<string> result;
        for (int i = 1; i <= n; ++i) result.push_back(to_string(i));
        for (int i = 2; i < n; i += 3) result[i] = "Fizz";
        for (int i = 4; i < n; i += 5) result[i] = "Buzz";
        for (int i = 14; i < n; i += 15) result[i] = "FizzBuzz";
        return result;
    }
};

image.png

小结

BFS 更新最小次数,注意一维编号到二维编号的改变。附带简单题,少用取余数和除法也许能提高效率。

参考链接