第一节:字符串相关(最长公共前缀、无重复最长子串、最长回文子串)
一. 最长公共前缀
1. 题目描述
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""
。
详见:https://leetcode.cn/problems/longest-common-prefix/
难度:【简单】
2. 思路分析
(1). 默认以数组中的第1个元素为前缀 prefix
(2). 遍历数组的每一个元素
A. 利用indexof判断是否以该prefix为开头
B. 如果不是, 则将prefix从尾部减去1, 继续利用indexof判断
C. 如果是, 则跳出循环,进行数组中下一个元素的判断
(3). 当prefix的长度为0时, 表示没有公共前缀
3. 代码实操
function longestCommonPrefix(strs: string[]): string {
//边界判断
if (strs.length <= 0) return '';
//业务逻辑
let prefix = strs[0];
for (let i = 1; i < strs.length; i++) {
while (strs[i].indexOf(prefix) != 0) {
prefix = prefix.slice(0, prefix.length - 1);
if (prefix === '') return '';
}
}
return prefix;
}
二. 无重复最长子串
1. 题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
详见:https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/
难度:【中等】
2. 思路分析
这里采用双指针left、right的解题思路
(1). right指针负责从头扫描到尾部
(2). left指针默认指向0的位置,
(3). 在发现right指针出现重复字符的时候 并且 出现的位置要>=left位置, 将left改为之前出现字符位置+1
(4). 每次遍历可以求出
currentLength=right-left+1;
maxLength=Math.Max(maxLength,currentLength)
补充:
A. 字符串str可以直接通过 str[i] 的模式获取第i个位置的字符
B. 用map<string,number>记录 s[i]的值 和 对应的索引
3. 代码实操
function lengthOfLongestSubstring(s: string): number {
let n = s.length;
let map = new Map<string, number>(); //map结构存放 s[i]的值 和 对应的索引
let maxLength = 0; //最大长度
//双指针left,right
let left = 0;
for (let right = 0; right < n; right++) {
const sValue = s[right];
//1. 判断之前是否出现过该字符
if (map.has(sValue) && map.get(sValue)! >= left) {
left = map.get(sValue)! + 1; //表示出现过
}
//2. 存放到map里 (必须放在上面的判断之后)
map.set(sValue, right);
//3. 获取当前长度
let currentLength = right - left + 1;
//4. 获取最大长度
maxLength = Math.max(maxLength, currentLength);
}
return maxLength;
}
三. 最长回文子串
1. 题目描述
给你一个字符串 s,找到 s 中最长的回文子串, 并输出。 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
详见: https://leetcode.cn/problems/longest-palindromic-substring/description/
难度:【中等】
2. 思路分析-中心扩展法
(1). 先封装一个中心扩展算法centerExpand,根据left和right指针位置,求回文串长度
(2). 定义最大回文串的开始、结束索引,start、end
(3). 开始遍历
A. 有两种回文情况, 需要分别计算回文长度
B. 求出上述两种情况的最大长度, 和 end-start+1 比较。 (也有写end-start的, end-start+1 表示的是回文长度)
如果大于等于话,需要重新对start 和 end 赋值, 借助上述求得 maxlength
(4). 最终根据start 和 end 求回文字符串最长的。
3. 代码实操
PS:centerExpand中,最后为什么是right-left-1呢?
举例子:str="abbc", left=1,right=2, 进入while遍历,跳出遍历的时候 left=0,right=3了,此时是索引不是回文字符串的索引,
而是额外执行了一次while内部操作, 回文串为bb,即长度为2, 即 right-left-1 。
function longestPalindrome(s: string): string {
//边界判断
let n = s.length;
if (n <= 1) return s;
//遍历求最大回文字符串
let start = 0; //最大回文串的开始索引
let end = 0; //最大回文串的结束索引
for (let i = 0; i < n; i++) {
//两种回文情况
let length1 = centerExpand(s, i, i); // 如:cabad
let length2 = centerExpand(s, i, i + 1); // 如:dbaabc
let maxLength = Math.max(length1, length2);
//求最大回文串开始、结束的索引
//新的长度比原来保存的start/end要长, 重新赋值
if (maxLength > end - start + 1) {
const left = i - Math.floor((maxLength - 1) / 2); //要先-1
const right = i + Math.floor(maxLength / 2);
start = left;
end = right;
}
}
return s.substring(start, end + 1); // [), 所以要截取到end位置,需要传入end+1
}
/**
* 求指定位置的回文字符串长度
* @param s 待求的字符串
* @param left 指针1
* @param right 指针2
* @returns
*/
function centerExpand(s: string, left: number, right: number): number {
while (left >= 0 && right < s.length && s[left] === s[right]) {
left--;
right++;
}
return right - left - 1; //回文字符串长度 (公式详见上面的思路分析)
}
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。