LeetCode之路:551. Student Attendance Record I

一、引言

这道题还是比较简单的,就当惬意陶冶情操了吧 ^_^

看下题目:

You are given a string representing an attendance record for a student. The record only contains the following three characters:

1.’A’: Absent.
2.’L’: Late.
3.’P’: Present.

A student could be rewarded if his attendance record doesn’t contain more than one ‘A’ (absent) or more than two continuous ‘L’ (Late).

You need to return whether the student could be rewarded according to his attendance record.

Example1:
Input: “PPALLP”
Output: True

Example2:
Input: “PPALLL”
Output: False

简单翻译下:

给定一个学生的出勤记录,这份记录上只有三个字母能够出现,其中 ‘A’ 表示缺勤、’L’ 表示迟到、’P’ 表示出勤。

一个学生能够获奖的条件是,他的出勤记录中不能包含超过 1 次的 ‘A’ 和超过 2 次的连续的 ‘L’。

你需要返回这个学生是否能够获奖。

稍微读了下题目,大概了解了大意,这道题其实不难,重点就是看看输入字符串中有没有超过 1 次的 ‘A’ 和超过 2 次并且连续的 ‘L’。

二、std::stack:栈记录各个字母的出现次数

一说到连续出现,我就会想到 std::stack,只需要出现 ‘L’ 的时候压栈,不是 ‘L’ 的时候清空栈即可。

代码如下:

// my first soluton , runtime = 6 ms 
class Solution1 {
public:
    bool checkRecord(string s) {
        stack<char> a, l;
        for (auto i : s) {
            if (i == 'A') {
                if (a.size() == 1) return false;
                else a.push(i);
            }
            if (i == 'L') {
                if (l.size() == 2) return false;
                else l.push(i);
            }
            else while (l.size()) l.pop();
        }
        return true;
    }
};

这里对于 ‘A’ 和 ‘L’ 都使用了 std::stack 的栈结构来存储数据。

那么可不可以不使用栈呢?

三、一般变量:记录各个字母的出现状况

这里,我想抛开栈,直接使用两个变量来记录 ‘A’ 和 ‘L’ 的出现状况:

// my solution 2 , runtime = 3 ms
class Solution2 {
public:
    bool checkRecord(string s) {
        bool hasA = false;
        int countL = 0;
        for (auto i : s) {
            if (i == 'A') {
                if (hasA) return false;
                else hasA = true;
            }
            if (i == 'L') {
                if (countL == 2) return false;
                else countL++;
            }
            else countL = 0;
        }
        return true;
    }
};

这里,我使用了一个 bool 变量来标记 ‘A’ 是否已经出现,使用了一个 int 变量来记录 ‘L’ 的出现次数。

这里,能否简化下代码呢?毕竟那么多 if else 的嵌套很难看的:

// my solution 3 , runtime = 3 ms
class Solution3 {
public:
    bool checkRecord(string s) {
        int a = 0, l = 0;
        for (auto i : s) {
            if (i == 'A') a++;
            if (i == 'L') l++;
            else l = 0;
            if (a > 1 || l > 2) return false;
        }
        return true;
    }
};

这份代码的逻辑并没有什么不同,只是简化了下代码,在每次遍历的最后一部分进行返回的判断。

四、绝妙:一行代码可解!!!

本来这道题做到这里也就算结束了 T_T

可是我非要去百度查查别人的代码看看,于是乎发现了这么优雅的解法:

// perfect solution 4 , runtime = 6 ms
class Solution {
public:
    bool checkRecord(string s) {
        return !regex_search(s, regex("A.*A|LLL"));
    }
};

如果你对 C++ 的正则库熟悉的话,你也许一眼就能看懂。

这里我还是简要解释下:

A.*A|LLL 这句正则表达式的意思是,|之前表示第一个条件,寻找 A 之后(.*表示非换行符的一切字符重复 n 次)再出现一个 A,这种情况可以直接返回 false;另外一种条件,也就是 | 之后的条件,直接寻找 LLL三个 L 连续出现的情况,如果有的话,也可以直接返回 false。如果上述两种情况下都没有找到匹配的字符串,那么证明该出勤记录可以获奖,也就是应该返回 true。

一行代码的艺术!

真心膜拜大神!

四、总结

这道题还是比较简单的,值得一说的是 std::stack 栈结构的运用。

尽管这里使用栈并非最好的选择,但是使用栈总能带来逻辑上的语义化。另外,这里需要注意的是,std::stack 并没有提供 clear 函数,需要手动进行遍历弹出,至于原因,我记得在另外一篇博客涉及到 std::queue 中有谈到过,适配器不能直接操纵底层容器的数据。

这些题目说实话,真心不难,不过不难的题目也不能掉以轻心,好好分析优化代码才是王道。

^_^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值