常见算法基础题思路简析(六)-字符串篇
2017-09-28 22:12
357 查看
常见算法基础题思路简析(六)-字符串篇
标签: algorithms[TOC]
本文对和 字符串 有关的常见算法基础题思路分类进行分析和总结,并以 Java 为例,适当指出需要注意的编程细节
相关题目和代码在 GitHub: https://github.com/brianway/algorithms-learning
题目见
com.brianway.learning.algorithms.lectures.string包
最长无重复字符子串
题目见DistinctSubstring
思路:对于每个字符,向左延伸找无重复子串,要知道该字符(记为
s[i])上次在哪个位置出现过,还要知道之前其他字符中出现过重复且最近一次出现重复的那个位置 pre,则以
s[i]结尾的向左最长无重复的长度为:
s[i]上次出现位置和 pre 中较大者到现在
s[i]的距离。
//例子1 i:0 1 2 3 4 5 s:b a c b a d i=4 => s[4] = a, pre = 0(b 重复了),map[a] = 1(a 上次出现在 i=1) => cur = 4-1 = 3, 即 cba i=5 => s[5] = d, pre = 1(a 重复了), map[d] = -1 => cur = 5-1 =4, 即 cbad //例子2 i:0 1 2 3 4 5 s:a b c b a d i=4 => s[4] = a, pre = 1(b 重复了), map[a] = 0(a 上次出现在 i=0) => cur = 4-1 = 3, 即 cba i=5 => s[5] = d, pre = 1(b 重复了), map[d] = -1 => cur = 5-1 =4, 即 cbad
使用一个哈希表
map[256]来记录每种字符之前最新出现过的位置。
使用一个整型变量 pre 来记录以
s[i-1]结尾的字符串向左延伸且无重复字符时的最左下标(不包括该下标)。
对字符串中每个字符
s[i]进行如下操作:
对字符串中每个字符,找出
pre和
map[s[i]]中的较大值并更新为
pre
以当前字符
s[i]结尾向左无重复的长度则为
cur = i - pre
根据这个 cur 和历史最大长度比较,更新最大长度
更新
map[s[i]]为 i
注意:
map 中每个元素和 pre 均初始值为 -1
有个现象:当未出现过某字符且字符均未出现过重复时,
pre和
map[s[i]]均为 -1,
cur = i+1,cur 随 i 递增
拓扑结构相同子树
题目见IdenticalTree
思路:
使用特殊格式打印的二叉树中序遍历结果时唯一的,打印两个树的中序遍历字符串
使用 KMP 算法进行子串匹配,能匹配则
注意:
中序遍历时,空节点也要打印,所有值要以特殊字符结尾以免歧义
KMP 的原理、实现以及小优化
字符串匹配的KMP算法
从头到尾彻底理解KMP
合法括号序列
题目见Parenthesis
思路:每个右括号出现时必已有一个左括号与之对应,计数即可,正负抵消。对每个元素进行如下操作:
遇到非括号字符返回 false
遇到左括号则计数器加一
遇到右括号则计数器减一,计数器为负值则返回 false
循环结束计数器值为零则 true,否则 false
拼接最小字典序
题目见Prior
思路:排序不是以单个字符串来比较,而是把待比较的两个字符串(记为 sa 和 sb)拼接起来进行比较,即比较 sa+sb 和 sb+sa 的字典序
注意:
由于两个串无论什么顺序拼接,拼接后字符串长度相同,所以无论谁在前,拼接后的串对其他字符串影响是一致的
空格替换
题目见Replacement
思路:
先统计下空格数量,分配空间
直接逐个字符复制,遇到空格就替换即可
注意:
新的字符串长度为
length + 2 * count,length 为原字符串长度, count 为空格个数,
%20比空格多了两个字符
句子逆序
题目见Reverse
思路:
先对整个字符串反转
再对以空格分隔的每个单词反转
注意:
能做到 in place 反转,无需额外空间,有点像“负负得正”
每个单词反转是以其末尾的空格触发的,所以对最后一个单词,需要单独判断处理
两串旋转
题目见Rotation
思路:
判断两串是否长度相等
将原串与自身拼接,看另一字符串是否是拼接串的子串即可
词语变形
题目见Transform
思路:
判断两串长度是否相等
遍历 A 串,统计 A 串中每种字符出现的次数(计数累加)
遍历 B 串,做 2 中的统计结果做减法,若 B 中出现了 A 中未出现的字符或者 B 中某种字符出现次数比 A 多(表现形式为:减 1 前
counts[b[i]] == 0),返回 false,否则 true
注意:
遍历 B 串不是计数累加而是利用 A 的结果
字符串移位问题
题目见Translation
思路:以移位长度为分界点,分别将各部分对其中轴线做镜像反转,再对整个字符串以其中轴线做镜像反转。
将下标
0 ~ len-1的字符反转
将下标
len ~ n-1的字符反转
将整个字符串
0 ~ n-1反转
注意:
无需申请额外空间
各部分做了两次镜像反转,所以内部保持相对顺序不变
作者@brianway更多文章:个人网站
|CSDN
|oschina
相关文章推荐
- 常见算法基础题思路简析(六)-字符串篇
- 常见算法基础题思路简析(二)-链表篇
- 常见算法基础题思路简析(三)-二叉树篇
- 常见算法基础题思路简析(三)-二叉树篇
- 常见算法基础题思路简析(四)-二分搜索篇
- 常见算法基础题思路简析(四)-二分搜索篇
- 常见算法基础题思路简析(五)-队列和栈篇
- 常见算法基础题思路简析(五)-队列和栈篇
- 常见算法基础题思路简析(一)-排序篇
- 常见算法基础题思路简析(一)-排序篇
- 常见算法基础题思路简析(一)-排序篇
- 常见算法基础题思路简析(二)-链表篇
- 基础算法----判断字符串是否为另一个字符串的真子集
- 常见算法思路总结
- (1.2.3.1)字符串常见算法
- 基础算法(二) ———— 判断一个字符串中的所有字符是否都不
- 【算法】の基础——常见排序算法
- 贪心算法基础之完美字符串 51nod 贪心总结
- 算法基础:删除字符串中出现次数最少的字符(Golang实现)
- 字符串组合算法--但是思路还没全部搞明白