简单题
7. 整数反转
每次截取末位,*10,叠加,直到原数x = 0
处理溢出,整数范围在-2147483648~2147483647,每次要溢出之前都是大于2147483647/10,或者小于-2147483648/10,所以只要判定一下即可
1 | class Solution { |
9. 回文数
- 首先,负数不是回文数
- 对非负数,先得到逆序数,再判断是否和原数相等
1 | class Solution { |
官方题解说只要翻转一半的数字就可以了,同时可以避免溢出,如何判断到一半了呢?条件是x < lastx
12345 - 54321,12345|0,1234|5,123|54,12|543。翻转到123 和543是否相等?12和54
123456-654321,123456|0,12345|6,12345|65,123|654。翻转到123和654是否相等,
修改了代码如下
1 | class Solution { |
13. 罗马数字转整数
一位位处理即可,遇到IXC,就再看下一位一起处理。
1 | class Solution { |
上面的方法写的不够简洁,遇到改需求(比如IXC之类的改成别的字符会比较麻烦)会大改代码,看了一篇写的挺简洁的,即把我的help函数改成查表法,值得注意的是第14行的if (i+1 < s.length() && hash[s[i]-'C'] < hash[s[i+1]-'C'])
的第二个条件,假如出现小面额在大面额之前的情况,我一开始以为这个写法有漏洞,比如IM这种情况,后来想想这种情况不属于合法输入,所以可以。
1 | class Solution { |
14. 最长公共前缀
从下标0开始一列列对比
1 | class Solution { |
20. 有效的括号
用一个栈,遇到左括号入栈,遇到右括号看栈是否为空and栈顶是否为对应左括号。最后看栈是否为空
1 | class Solution { |
可以加一些判断过滤:
- s.length()为奇数
- 栈深度大于s.length()/2时,后面有再多的右括号也消化不了
- 栈深度大于剩余长度时,后面有再多的右括号也消化不了(强于2)
但其实没怎么改进速度
1 | class Solution { |
21. 合并两个有序链表
逐个比较两个链表的当前元素,小的插入新链表,然后当前元素后移一位
1 | /** |
上面的写法没有利用l1和l2的空间,下面重复利用l1和l2的空间。用一个指针prev记录上一个选中的节点,然后选中当前节点cur后,将prev->next=cur。
1 | /** |
27. 移除元素
迭代器的使用
1 | class Solution { |
第二种办法,注意到题目里说元素顺序可以改变,所以可以不真正删除元素,而是把元素调到数组的最后面去(用时反而比上面的解法慢,不解)
1 | class Solution { |
28. 实现strStr()
改进的kmp
1 | class Solution { |
sunday
1 | class Solution { |
35. 搜索插入位置
二分查找递归版
1 | class Solution { |
二分查找迭代版
1 | class Solution { |
38. 外观数列
BF,枚举之前的字符串,处理每个字符串的方法,遇到相同的字符,计数器+1,遇到不同的字符,将计数器和当前字符添加到nstr的尾部
1 | class Solution { |
困难题
4. 寻找两个有序数组的中位数
要求时间复杂度O(log(m+n)),想法每次砍掉一半的候选人,但出现了问题。
假如m和n均为奇数,或者均为偶数,那么中位数必然是(ai+bj)/2,如果m和n一奇一偶,那么中位数必然是ai或者bj。
每次砍掉一半,意味着m和n的奇偶性会变化,然后出事。
比如奇数,还是奇数,xxxx但是偶数,有可能变成奇数或者偶数。所以一奇一偶没问题。
两奇或者两偶的需要找第(m+n)/2-1大和(m+n)/2大的数
- 一种想法是:把两个数组中最大的一个数去掉,变成了一奇一偶,算出原第(m+n)/2-1大的数;把最小的一个数也去掉,变成了一奇一偶,算出原第(m+n)/2-1大的数,然后相加除以二
- 不过这样相当于算了两遍,改进一下,算出原第(m+n)/2-1大的数后,下一个数的候选人是这个数所在数组的后一个数,或者另一个数组的二分查找的刚好大于等于这个数的数
41. 缺失的第一个正数
给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。
1 | class Solution { |
1019. 链表中的下一个更大节点
对于链表 [2, 5, 1, 1, 4]
next[] = [5, 0, 4, 4, 0]
1 | /** |
896. 单调数列
判断一个数列是否是单调递增or单调递减,解法1,往后看;解法2,两个单调栈
1 | class Solution { |
1 | class Solution { |
84. 柱状图中最大的矩形
解法1:暴力
1 | class Solution { |
解法2:单调栈
观察到,我们需要的是一个柱子的,左边第一个比他小的,和右边第一个比他小的;而单调递增栈恰好有这个性质:当一个元素被pop的时候,此刻的栈顶是左边第一个比他小的,让他pop的元素是右边第一个比他小的
1 | class Solution { |
剑指 Offer 09. 用两个栈实现队列
1 | class CQueue { |
300. 最长上升子序列
解法1:
dp[i] 代表以nums[i]作为首元素的最长上升子序列的长度
转移方程:dp[i] = max(1, max(dp[j]) + 1) (j > i, num[j] > nums[i])
1 | class Solution: |
x. 矩阵连乘
思考:矩阵Ai … Aj 的乘法次数记做A[i, j],最后一次左右两坨矩阵的乘法位置记做k,最少次数是 min(A[i, k] + A[k+1, j] + p[i] * p[k] * p[j])
150. 逆波兰表达式求值
只有+-*/四个运算符
1 | class Solution { |
224. 基本计算器
包含()+-,非负整数和空格
解法1:中缀转后缀,计算后缀
1 | class Solution { |
解法2:先词法分析,找exp的dominant operator,递归求解exp1 op exp2
1 | class Solution { |