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

432 阅读5分钟

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

写在前面

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

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

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

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

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

2021.6.17 每日一题

65. 有效数字

这题目真是绝了,判断正常的数字,回忆起了被谭浩强小红书支配的恐惧。。。各种各样奇怪的选择题让你选合法的数字。

这道题给人一种在玩 FPGA 的感觉。提到 FPGA,最重要的就是状态机了,这道题当然可以用状态机来做。请不要过度神化状态机(自动机),反正我感觉学过编译原理的专业都喜欢神化自动机,但是基本上被数电折磨的死去活来的专业都拿状态机当自己的朋友。实际上不管叫它状态机还是自动机它都是一个东西,KMP 算法里会使用到它,正则的基础思想也是它,搞 FPGA 一定会用这个东西来设计自己的小系统工作流程。

所以,实际上分类讨论,正则,翻译,这些解题思路背后真正用到的还是状态机。。。只是这些解题思路用到了语言里封装好的工具。那么我们自己要如何使用最原始最本质的状态机思想来解这道题呢?建议各位先去看这道题的精选回答,我觉得这个题解比官方题解写的要好。

状态机一定有一个初始状态和若干可接受状态,可接收状态的数量看设计者对问题的理解以及分割,毕竟状态机是为了方便人处理问题而出现的,不是专门拿出来难为人的东西。这个东西就是用来规范分情况讨论和拆分子问题的思维步骤的工具。我认为一开始读入若干空格是初始状态,然后就是读入符号,然后读入数字,然后读入小数点,然后读入数字,然后读入科学计数法的标志 eE,然后读入符号,然后读入数字,最后结束的时候可能会读入若干空格,这样最复杂的数字读入流程就结束了。然后从最复杂的流程开枝散叶看中间那些步骤可以跳过,比如说符号可以跳过,比如说小数点可以跳过,比如说科学计数法标志可以跳过。然后就是整理思路画出状态转移图(不要把状态机和动态规划混为一谈,状态转移图也是为了理思路,不重不漏,方便阅读就行),我这里借用一下精选回答的状态转移图:

state transition diagram

不知各位能否看懂,图里面从左到右0到5这个状态是最复杂情况,其他线描述的是可以跳步的情况,如果一个字符串读入,还没有到最终情况就读完了,那么这种停在半中央挡道的东西都不是正常的数,停在半中央挡道并没有转移到我们的可接受状态,理所当然是不能被接受的状态。

如果这个图没有看懂,那么看一下这张图对应的状态跳转表,看状态跳转表就跟做心理测试一样,这道题你回答了这个选项,请你跳转到某某问题上继续测试,最后会落在一系列心里测试结果的某一种里,这种状态转移表应该是最好接受的状态机的描述形式了。

stateblank+/-0-9.e/Eother
00162-1-1
1-1-162-1-1
2-1-13-1-1-1
38-13-14-1
4-175-1-1-1
58-15-1-1-1
68-1634-1
7-1-15-1-1-1
88-1-1-1-1-1

作者:user8973 链接:leetcode-cn.com/problems/va… 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

带上原文链接,各位看不懂我在说啥去看原文就行。我觉得问题说到这个份上已经完全说明白了,之后就是把这些东西翻译成代码。


class Solution {
public:
    bool isNumber(string s) {
        if (s.empty()) {
            return false;
        }
        int n = s.size();

        int state = 0;
        vector<bool> finals({0, 0, 0, 1, 0, 1, 1, 0, 1});
        vector<vector<int>> transfer({
                { 0,  1,  6,  2, -1, -1},
                {-1, -1,  6,  2, -1, -1},
                {-1, -1,  3, -1, -1, -1},
                { 8, -1,  3, -1,  4, -1},
                {-1,  7,  5, -1, -1, -1},
                { 8, -1,  5, -1, -1, -1},
                { 8, -1,  6,  3,  4, -1},
                {-1, -1,  5, -1, -1, -1},
                { 8, -1, -1, -1, -1, -1},
                });

        for (int i = 0; i < n; i++) {
            state = transfer[state][_make(s[i])];
            if(state < 0) return false;
        }
        return finals[state];
    }

private:
    int _make(const char& c) {
        switch(c) {
            case ' ': return 0;
            case '+': return 1;
            case '-': return 1;
            case '.': return 3;
            case 'e': return 4;
            case 'E': return 4;
            default: return _number(c);
        }
    }

    int _number(const char& c) {
        if (c >= '0' && c <= '9'){
            return 2;
        } else {
            return 5;
        }
    }
};

image.png

2021.6.17 每日一题下面的题

1480. 一维数组的动态和

这题可以直接秒了,简单题面试官就喜欢看你的代码规范,一般工程里传这种东西都是这么写 vector<int> runningSum(const vector<int>& nums),然后实现的时候自己复制一份自己随便玩,原来传进来的不要乱改。

image.png

小结

状态机判断合法的数字,简单题注重代码规范

参考链接