Leetcode 解题报告

据说刷完leetcode是准备编程面试的第一步。想到明年可能就要开始找工作了,先准备着吧。计划今年11月份前做完,大概平均每天2-3题,难度应该不大,贵在坚持!代码放在github上,地址:https://github.com/xingjian-f/Leetcode-solution简略解题报告1 Two Sum三种解法:1 暴力枚举所有的两两组合,检查它们的和是否等于
摘要由CSDN通过智能技术生成

据说刷完leetcode是准备编程面试的第一步。想到明年可能就要开始找工作了,先准备着吧。


计划今年11月份前做完,大概平均每天2-3题,难度应该不大,贵在坚持!
代码放在github上,地址:https://github.com/xingjian-f/Leetcode-solution

(2016.10.1 更新,从6.30开始,截止到10.1,三个月时间,目前做题情况 solved 256/ 390 problems. 做完了所有未加锁的初等、中等和部分hard题目。还有一个月时间,做完剩下的hard题目,加油!2017.9.15更新,目前做题情况345 / 662,找工作结束了,后面好好写论文了,应该也不会再怎么做了。

简略解题报告

1 Two Sum
三种解法:
1 暴力枚举所有的两两组合,检查它们的和是否等于目标,复杂度O(n^2)
2 建字典,用一个列表记录每个数字在哪些位置出现过(因为一个数字可能出现多次),然后重新扫描一遍所有输入数字,检查目标和它所对应的差值是否在字典中出现过,以及它们的位置是否重叠。根据建字典的方法,复杂度会有不同。哈希实现,O(n), 树实现,O(nlogn)。
3 不用建字典,先对输入数组排序,然后用二分搜索去查找。复杂度O(nlogn)

2 Add Two Numbers
整数加法,但数字是用链表表示的。可以模拟加法,这个方法一定要注意5+5=10这种多生成了一位的情况,很容易忽略(我就wa了一次),或者先把两个数从链表解释出来,然后做加法,再解释回链表的表示,问题是要注意这个可能需要大整数加法,那又回到了模拟加法的问题,不过python这种内置大整数加法的语言就不用考虑这个问题了。

3  Longest Substring Without Repeating Characters
two pointers 方法,O(n)解决。需要字典记录当前子串每个字符出现的位置,根据字典的实现方法不同,也可能O(nlogn)。

4  Median of Two Sorted Arrays
复杂度要求O(log(m+n)), 不过我觉得最快也就是O(2*logm*logn),类似求第K大数。实现写的是O(n+m)的合并操作,然后在有序数组上求中位数,也可以过。

5 Longest Palindromic Substring
用dp[i][j]表示(i-j)这一子串是否为回文串,复杂度O(n^2),按理说1000长度的数据是可以过的,但是python实在太慢,用这种方法会超时。
需要优化。若dp[i]表示,以i结尾的最长子串长度,maxl表示目前已知的最长长度。因为只有当dp[i]大于maxl时,才有求得必要,所以只考虑dp[i]大于maxl的情况,只有如下两种:
1 (i-maxl~i) 是回文串 , dp[i] = maxl+1
2 (i-maxl-1~i) 是回文串, dp[i] = maxl+2
dp[i]不可能有更大的情况,因为有的话,dp[i-1] 一定大于maxl。
这个优化,可以使枚举情况数大大较少, 复杂度依然是O(n^2)。实际代码中dp可以不用记录。

6. ZigZag Conversion
可以直接模拟,也可以找数学表达式,我选择了第二种自己相对弱的方式。
n表示一共有多少行,i表示现在计算的第i行,k表示枚举到第几个“峰”。那么同一行中每一个峰,左右两边各对应一个数字,它们的表达式分别为
-i + (2*n-2) * k 和 i + (2*n-2*k) ,然后注意判断边界。另外注意!当n==1时,这个公式不成立,直接返回输入的字符串即可。

7. Reverse Integer
Leetcode上题目的特点就是坑多,一定要想清楚测试用例,确保程序考虑周全。负数和0都很容易想到,但是题目还要求考虑整数反转后数值太大溢出的问题,但python是没有这个问题的,直接转str,反转,再转int就可以了,不过题目要求超出32位整数范围输出0。

8. String to Integer (atoi)
按照题目要求做就好了,真正面试的时候,关键部分应该在于主动问出所有可能的输入情况以及相应要求的应对措施。

9. Palindrome Number
注意负数不是回文数,面试要自己问。

10. Regular Expression Matching
要求s和模式串p完全匹配,所以用p贪心去匹配s是不行的,因为有可能p有的部分s不能满足。可以先考虑回溯法,计算s[i:]和p[j:]能否匹配,找到可行策略后,加个dp数组变成记忆化搜索高效求解。
如果p[j+1]=='*':
dp[i][j] = dp[i][j+2] or (match(s[i],p[j]) and (dp[i+1][j+2] or dp[i+1][j]))
else:
dp[i][j] = match(s[i],p[j]) and dp[i+1][j+1]
然后注意考虑清楚边界条件。

11. Container With Most Water
假设选择的柱子是i和j,那么题目就是要最大化loss = min(height[i], height[j])*(j-i)。
三种方法:
假设j是右柱,且是容器短板,那么要loss最大,就要找j左边的,比height[j]大的柱子i,且i离j最远,往左扫描一遍去找,算法整体复杂度O(n^2)。
有没有更快的方法呢?可以维护一个所有柱子高度为key,这个高度对应的最左边柱子的下标为value的列表,然后只需要在这个表中,二分查找最小的大于等于height[j]的那个柱子的下标即可,复杂度O(nlogn)。
上面两个方法都假设j是右柱且是短板,但有时可能是左柱是短板,处理方法是把输入反过来用函数再求一遍,取两者的较大值。
还能不能更快?要想loss最大, 可以先让j-i最大,即two pointers分别选最左和最右,但loss还取决于height,所以需要移动pointers,怎么移呢?有一点可以明确的是,two pointers中的高度小的那一个,一定不会再作为后面求最大值时的参考柱子,因为如果选它,后面容器的宽度会减小,而高度永远都不会大于这根柱子,所以loss永远不会变大。由此得到策略,移动two pointers中高度小的那个,如果两个一样怎么办?随便选哪个都可以。复杂度O(n)。

12. Integer to Roman
跳过

13. Roman to Integer
跳过

14. Longest Common Prefix
简单扫描。

15. 3Sum
当选定一个数之后,再选两个数就变成了2sum问题,对于排好序的数组,2sum问题是O(n)可以解决的,因此整体复杂度为O(n^2)。但是,题目要求去重,用set实现,复杂度O(n^2*logn^2),但实际答案数应该远小于n^2,所以还是很快的。

16. 3Sum Closest
和15几乎一样,不再赘述。

17. Letter Combinations of a Phone Number
python: itertools.product

18. 4Sum
多枚举一个元素,然后问题就变为3sum了,复杂度O(n^3)。有种做法,先预处理出两两之和,再枚举和二分查找,有人认为这种做法是O(n^2logn),实际不是。因为题目要求找到所有不同的解,所以不管解法是什么,答案最多有O(n^3)个,任何解法都绕不开这个下界。由这个问题,可以拓展到K-Sum问题,都是通过枚举不断规约,直到求2sum问题,复杂度O(n^k-1)。

19. Remove Nth Node From End of List
按描述写。

20. Valid Parentheses
栈模拟

21. Merge Two Sorted Lists
链表模拟。

22. Generate Parentheses
dfs。 注意,认为p(n) = ['()' + p(n-1), '('+p(n-1)+')', p(n-1)+'()'] 是错的,例如(())(())就不是,这种假设不要轻易断言。

23. Merge k Sorted Lists
依次一个一个Merge Two Sorted Lists,复杂度O(k^2),采用归并两两merge,复杂度降为O(klogk)。

24. Swap Nodes in Pairs
按描述写,注意head也变了。

25. Reverse Nodes in k-Group
还记得当年保研机试时用了一个半小时还是挂在了这道题上,重新再做,还是挂在了上面,用了一个下午才调出来,并且姿势极丑!。。。sad,以后有时间要再重做一次。

26. Remove Duplicates from Sorted Array
按描述写。

27. Remove Element
和上题一样。

28. Implement strStr()
KMP,不过和直接用python的index方法时间差别非常小。

29. Divide Two Integers
模拟除法,用类似快速幂的方法。

30. Substring with Concatenation of All Words

31. Next Permutation
这里定义的next permutation,是字典序比当前大1的排列,可以从整数加法的角度考虑,整数加法直接末位加1,然后进位就可以了。但这里因为能使用的数是有限的,末位想变大,只能从前面比它大的位交换过来,而这样的话,前面的位就会变小,那字典序反而减小了。所以只能考虑末位前面的,尽量靠近末位的位置(使字典序最小),用这个位置后面的某个比它大的数,来和它交换,然后令后面的所有数字从小到大排序。
数学上表示,假设i是要找的位置,那么要满足,nums[i] < max(nums[i+1:]), 并且在nums[i+1:]中,nums[k] > nums[k+1] ,所以就是从右往左找满足 nums[i] < nums[i+1] 的第一个位置。

32. Longest Valid Parentheses
two pointers方法,用cntl和cntr分别记录指针间左括号和右括号的个数,若左大于右,则右指针右移,因为以左指针为首的有效序列还可能更长,否则左指针右移,因为以左指针为首的序列,不可能再有更长的有效长度。当左右指针相同,左还需右移时,则两个指针同时右移。当左右括号个数相等时,可以更新最长长度。但这么做有一个没有考虑的情况,"(()",即左括号数一直比右多,答案就不会更新。解决方法是,再从右往左扫,并维护右括号大于等于左括号数的最长序列。

33. Search in Rotated Sorted Array
先二分找到翻转轴的位置,再正常二分查找即可。

34. Search for a Range
二分查找

35. Search Insert Position
二分查找

36. Valid Sudoku
按描述写

38. Count and Say
跳过

39. Combination Sum
完全背包,解法几乎和40题相同,不赘述。

40. Combination Sum II
0-1背包问题,要求输出答案,因为没给target范围,于是dp实现用了dfs搜索,字典记录状态(nb, rem) 是否有答案,即选择到第nb个物品,还剩rem容量,是否有可能达到。

41. First Missing Positive
不让用额外的内存,但可以用输入的那一块内存,想到这个剩下的就简单了。

42. Trapping Rain Water
每块trap water的特点是,设i,j分别为左右柱,则a[k]<min(a[i],a[j]) (i<k<j), 并且不存在x<i and y>j,使得a[k]<min(a[x],a[y]) (x<k<y)。 这样,由于第一个柱子一定是左柱,那只需要往右找直到出现比它高的柱子,再继续往右则不能满足前面的约束条件了。这样就找到了第一个trap area,然后以右柱作为新的左柱继续找。注意,[3,2,1,2,1]这种找不到比左柱高的情况,只需倒过来找一遍即可。

43. Multiply Strings
大整数乘法.

44. Wildcard Matching
类似10.

45. Jump Game II
开始想用记忆化搜索,爆栈了,查了一下,发现python最多递归1000层,改用bfs,超时,这时才发现自己把复杂度算错了,本以为O(n),实际上每次拓展的时候,用时可能是O(n)而不是O(1),所以复杂度O(n^2)。仔细考虑,其实只用维护一个目前能向右跳到的最远点,然后不断迭代更新这个值即可。

46. Permutations
生成全排列.

47. Permutations II
unique 全排列.

48. Rotate Image
原地顺时针旋转n*n矩阵90度.

49. Group Anagrams
按描述写.

50. Pow(x, n)
注意n为负的情况.

53. Maximum Subarray
最大子串和.

54. Spiral Matrix
矩阵蛇形输出.

55. Jump Game
类似45.

58. Length of Last Word
按描述写.

59. Spiral Matrix II
按描述写.

60. Permutation Sequence
第k个permutation可以直接算出来,不用一一枚举。假设当前序列长度为len,那么这个序列的第k个排列与tmp=factorial(length-1)有关。

61. Rotate List
维护三个指针。

62. Unique Paths
组合数公式

63. Unique Paths II
dp

64. Minimum Path Sum
dp

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值