LeetCode Weekly Contest 28
很长时间没有做比赛了。题目不算难,但是临场很不冷静,二三两题题意看错,第一题大水题WA四次,最后一题没时间想。一直对自己的临场发挥很不满意,脑子总是转不起来,很佩服那些20分钟就能完赛的选手。
Student Attendance Record I
签到题。给定一个由P,L,A三个字母组成的串,表示学生的出勤情况。如果A不超过1个,连续的L不超过2两个,那么这个学生就可以得到奖励,反之不行。判断该学生能否得到奖励。
对L的计数容易出错,需要仔细。
Optimal Division
想明白就很简单的一个题。不管哪一种运算次序,都是把第一个整数不断除除除……要使商最大,只要使第一个整数的除数尽可能小,而要做到这一点,只要让后面2nd~nth的数依次相除即可。
出乎意料的简单……
Split Assembled Strings
看错了一个题意:字符串要按照原次序相接。
先枚举被切割的字符串,一共有strs.size()个。再枚举切割的位置,可以得到每一个切割后的串。搜索字典序最大的串即可。复杂度是 O(n2) ,n是字符串的总长度。
有一个减少搜索量的地方。对于一个选定的被切割字符串,不必枚举所有可切割点。先找出最大的字母,然后在它们边上切割就行了。
Student Attendance Record II
还是那个记录学生出勤的字符串。这一次问的,是一个长为n的出勤记录,rewardable的可能情况有多少种?最终答案模上一个大数。
这是个计数问题,可以用DP来做。我第一次想的方法很接近答案,我当时是这么想的:
dp[i]表示长度为i的出勤记录rewardable的情况数量。
dp_0A[i]表示长度为i的出勤记录,rewardable且不含A的情况数量。
dp_0L[i]表示长度为i的出勤记录,rewardable且结尾不是L的情况数量。
dp[i]的转移方程是:
dp(i)=dp(i−1)+dp_0A(i−1)+dp_0L(i−1)+dp_0L(i−2)
对应结尾为P,A,L和LL四种情况。
dp_0L[i]的转移方程是:
dp_0L(i)=dp(i−1)+dp_0A(i−1)
对应结尾为P,A两种情况
但是dp_0A[i]不知道该怎么求了。
巧妙的地方在于,A其实可以放到最后考虑。我们可以先统计不含A的合法记录种数,然后把A插进去即可。这样只需要两个状态dp和dp_0L,定义同上。
其他
C++11里有一个to_string函数,在c++ string里。mingw-g++认不出这个函数,说没有定义,查了stackOverflow之后,发现这是mingw-g++的bug,需要打patch解决,但是patch本身还可能有问题。坑得不行。。。