LeetCode刷题心得
前言
假期在家刷算法题,随手写下一些心得,便于学习和回忆。
两数相加【中等】
题目主要是要记得进位,尤其是比如555+555这种最后还要再进位的情况,要考虑好。链表的使用还是有些生疏。2020/7/5
失误点:
两个链表的指针值域越界了,其他问题不大。
收获:
一种新的方法:
int i = (n == true) ? 0 : 1;
这个用法的意思是n是否为true,是,i= 0;否,i =1;
无重复字符的最长子串【中等】
这道题目主要从指针入手,采用滑动窗口的方法解题。设置左右指针,指针中间是我们需要的字符串。解题方法很巧妙,避免了很多重复的判断。2020/7/5
失误点:
主要是容易越界,要注意值范围;
字符串的遍历要用charAt(i)来获取字符串的元素!
收获:
学会了使用java里面的哈希集合,add方法和判断是否有重复元素的contains方法(真的很方便)。
路径总和【简单】
这道题既然是简单,当然就要求快,看到题的第一反应就是递归。2020/7/7
失误点:
递归条件不清晰,不知道怎么设置条件。
收获:
掌握了一种二叉树的递归方法。
寻找两个正序数组的中位数【困难】
这道题乍一看觉得两个数组都给了正序那么找中位数应该很简单才对,仔细一想,情况有很多,而且条件限制了时间复杂度为log(m+n),首先想到的是使用两个指针通过两个指针比较大小来找中位数(类似归并算法),比较复杂需要分奇偶的情况,复杂的同时时间复杂度应该为(m+n)/2+1,不符合要求。参考了题解之后,选择使用求k小的数字,用递归实现。感觉上很类似官方给的二分求法。
失误点:
时间复杂度考虑不全,其次没有把握两种情况的统一点,我将问题分为奇偶来解决,题解是通过奇偶的统一点将两种情况合二为一解决。算法经验少,还要多看看一些经典算法。
收获:
看到了很多二分+递归的解决方法,感觉很厉害,值得借鉴。学会统合多种情况,抓住共同点。涉及时间复杂度log的基本都要用二分法来解决。
跳水板【简单】
这道理只设置了短板和长板,挺简单,主要是题目中的要求输出从小到大需要注意一下。2020/7/8
失误点:
一开始没有考虑到k为0以及两块门板都是一样的情况。
收获:
简单的ax+by式子。
最长回文子串【中等】
乍一看感觉很简单,仔细推敲需要用到字符串的处理,这一直是我个人的短板,所以做起来磕磕绊绊的,思路是正确的,一些特殊情况也考虑了,有所进步。2020/7/8
失误点:
回文子串的判断可行,但是没有考虑到将子串全部列举,片面的考虑了回文子串的实行。
收获:
这次学习收获挺大,我一开始的思路就是讲解中的中心扩散法,考虑了两个以下字符串长度的情况,后来看到解析,决定用动态规划的方法(动态规划大法好),主要的问题就是解决状态转移方程,将第i至j个子串的问题转化为一个二位的dp数组,每个数组的值判断是否是回文子串,同时还可以利用之前计算出来的结果(假设abcdcba,你判断了两头的a,还需要考虑里面的bcdcb是不是回文子串)。简单来说动态规划的步骤就是:
- 计算状态转移方程
- 是的时候执行什么语句
- 否的时候如何进入下一个状态(或者与有关状态联系)
- 上面的是否可以互换
其次学到了将字符串分割为数组的toCharArray()方法和将字符串截取的substring【begin,stop)方法。注意开闭。
恢复空格【中等,面试题】
这道题一看就比较难,看了就不想做,但还是耐着性子看完了。第一反应就是可不可以归并来做,通过两个指针定位一个单词,和昨天的最长回文子串一样的做法,但再看一眼他要的是没有收录的字符数,未匹配的还要处理,那么一想就是动态规划了,找转移方程,没什么思路,秃头许久之后参考了题解。题解中采用了动态规划和字典树。这个字典树是很巧妙的,他用的是反向构造单词数,这么一来,我们只需要在遍历sentence时,遍历索引位置的前面就可以了。是一个双重循环,但减少了不必要的遍历,只遍历【j-i】之间的,而且只要有一个j不符合字典树,那么直接可以break让i向右。状态转移的条件设置的是缺陷数,(大概是昨天的题目印象比较深,我一直想要设置成dp【i】【j】这样子,搞了半天弄不出来】)事实证明,还是最好按照他想要求什么来设置转移方程。不能照搬2020/7/9.
失误点:
一开始的状态转移方程没有设置好,问题挺大
实际上没什么解这道题的思路
收获:
字典树的倒着运用,字典树学过,但在解题的时候很难去想到要用这个结合着来解题,而且这个倒着用也很妙,状态转移方程还要熟悉,动态规划问题有待进步。
最佳买卖股票时机含冷冻期【中等】
这道题需要的就是分析股票会存在什么状态,抓住这个问题就很好解决了。我的思路是借助dp,动态规划,因为资金是会和前面的收益以及当下的决策挂钩,一看就想到dp。2020/7/10
失误点:
考虑到状态了,但是没有想着做下去,实际顺着思路应该是可以完成的,需要一些自信。
收获:
动态规划的又一种使用方式,逐渐熟练。
Z字形变换【中等】
题目不难,考虑到Z字形上下输入之后,就可以发现只要判断在第一行和最后一行进行切换就可以了。难在不知道怎么选择数据结构和处理中间的空白部分。
失误点:
数据结构的选择和空白部分的处理。
收获:
参考题解知道了使用StringBuilder的链表结构,添加链表的append方法以及添加时候如果要按照行输入还要加一个get(i)行数。注意StringBuilder是一个动态对象,可以不断扩充,也可以选择限制他的长度(用Capacity属性),最后需要返回的时候,要注意动态对象不能直接返回,要用toString方法将对象静态为字符串输出。
计算右侧小于当前元素的个数【困难】
这道题描述起来简单,上来就有思路,直接双重循环暴力解,可惜,时间超时,时间复杂度为O(n2),无奈之下看了题解,题解的复杂度为O(nlogn)稍微少了一点,做法已经复杂了很多,建立索引数组来实现。2020/7/11
失误点:
时间超时
收获:
学会使用索引数组+归并排序(感觉挺麻烦),通过对索引的操作达到不需要直接改动原有链表,其实际是对索引数组进行切分了前后两组,然后通过归并实现两组各自的排序,最后将改动实现到链表上。