3 无重复字符的最长子串【中】
思路:感觉有点难的亚子..因为重复出现的位置无法预料,那么下一次寻找的开始位置如何确定,难道用暴力解法依次遍历?首次,如何判断和记录重复,每次用一个哈希表?
1 | class Solution { |
- 用滑动窗口替代复杂度为$O(n^2)$的暴力解法,核心是要记录下重复位置用于窗口滑动
- 定义一个 map 数据结构存储 (k, v),
Map<Character, Integer> map = new HashMap<>();
其中 key 值为字符,value 值为字符位置 +1,加 1 表示从字符位置后一个才开始不重 复, 同时存位置的方法可以从始至终只用一个哈希表即可 start = Math.max(map.get(alpha), start);
start取更大的值,一方面start保证不会后退;另一方面value 值为重复字符上一次的位置 +1,下一次的最长必不包含本次重复的这一段,故直接跳到本次重复第一个字符的下一位置
+无论是否更新 start,都会更新其 map 数据结构和结果 ansans = Math.max(ans, end - start + 1);
- 字符串方法:string.length() string.charAt(pos)
- hashmap方法:hashmap.containsKey(key) hashmap.put(key,value)
- Math.max(value1,…)
- 哈希表还可以直接用int[26] 来代替
时间复杂度:$O(n)$
空间复杂度:$O(min(n,m))$ m为字符集大小
5 最长回文子串【中】
思路:一般来说回文可以用栈判断,但这是一个动态问题。如果用栈的话,什么时候弹出其实感觉比较难判断。不如用双指针?
暴力解法
1 | public boolean isPalindromic(String s) { |
- 用双指针判断回文
时间复杂度:$O(n^3)$
空间复杂度:$O(1)$
暴力破解优化1
1 | public String longestPalindrome(String s) { |
boolean[][] P = new boolean[length][length]
存储判断结果矩阵- 最外层按长度来遍历
- 长度为 1 和 2 的单独判断,然后基于其向两边拓展
时间复杂度:$O(n^2)$ 空间换时间
空间复杂度:$O(n^2)$ — 可以优化
暴力破解优化2
1 | public String longestPalindrome7(String s) { |
- 下一对角线的遍历只用到了相邻的更长对角线的结果,那么用长度为n的数组,结果不断覆盖
- 根据递推公式,采用倒序遍历
- j-i+1为字符串长度len,len为1或者2,所以len<3即j-i<2,而用一维数组存储结果时len=1都为ture,所以长度为3只需要判断两端字符是否相等
时间复杂度:$O(n^2)$ 空间换时间
空间复杂度:$O(n)$
动态规化
再用一个逆序字符串,转化为最长公共子串问题,但是效率并不太高
中心扩展法
1 | public String longestPalindrome(String s) { |
- 从一个字符开始扩展,或者从两个字符之间开始扩展,所以总共有 n+n-1 个中心
start = i - (len - 1) / 2;end = i + len / 2;
确定回文字符串的起止位置
时间复杂度:$O(n^2)$
空间复杂度:$O(1)$ — 充分利用了回文对称的特点
Manacher’s 算法
1 | public String preProcess(String s) { |
- 加特殊字符 “#” 使字符串统一为奇数长度
- 用一个数组 P 保存从中心扩展的最大个数,而它刚好也是去掉 “#” 的原字符串的总长度;用 P 的下标 i 减去 P [ i ],再除以 2,就是原字符串的开头下标了
- 相比于中心拓展法,利用了前半部分的对称信息; 对称时分三种情况来讨论
时间复杂度:$O(n)$
空间复杂度:$O(n)$
6 Z字形变换【中】
思路:竖向和斜向的字符数相等,如何建立输出顺序与排列方式的联系?每 n+n-2 个数视为一组,这组元素以除最高和最低点外,每行有两个数。可以建立规律,后面的情况+模即2n-2
找规律
1 | class Solution { |
- StringBuilder 是一个可变对象,可以预分配缓冲区,这样,往StringBuilder中新增字符时,不会创建新的临时对象,支持链式操作。有.append(s) .insert(pos,s) .toString() 方法
时间复杂度:$O(n)$
空间复杂度:$O(n)$
按行排序
1 | class Solution { |
- 用字符串数组来存储,+号直接拼接在后面
- 用向下或向右来控制row是增还是减
loc == 0 || loc == numRows - 1
每到顶点时变换方向
时间复杂度:$O(n)$
空间复杂度:$O(n)$
8 字符串转换整数(atoi)【 中】
思路:寻找第一个非空格字符,没找到不转换。找到后若不是正负号也不是数字,不转换。若是正负号,记录符号,接着计算数值,计算数值:可以用栈? 连续数值之后的字符可以忽略。计算出整数值之后还要判断是否在有效区间内,溢出返回最大或最小值。
1 | class Solution { |
- 注意判断条件,哪些是可以并列的,以及先后顺序
- 直接用ret迭代,不用栈
- 32 位有符号整数范围 -2147483648 ~ +2147483647
- 如果没有+号这个溢出判断是不是有什么问题?范围缩小位?
时间复杂度:$O(n)$
空间复杂度:$O(1)$
10 正则表达式匹配【难】
思路:首先这是一个匹配问题,由于正则的存在使得模式串有极多的可能性,如何确定一某合理的比较顺序?若是字母,判断对应位是否相等?不等为false。为.继续匹配下一位。为*时,若前面无字符,继续;有字符,先移动继续移动目标串直至不为该字符,特别的若该字符为.,若已处于模式串末尾返回true;否则返回false
1 | class Solution { |
+return matchCore(s,sIndex+1,p,pIndex) || matchCore(s,sIndex,p,pIndex+2);
精髓