014 - 最长公共前缀(longest-common-prefix)
/*
* @Author: lvjingshuai
* @Date: 2019-07-13 15:29:55
* @Last Modified by: lvjingshuai
* @Last Modified time: 2019-08-07 10:16:25
*/
文章结构 |
---|
1、题目介绍 |
2、解题 |
2.1 解法 - 暴力破解 |
2.2 解法 - 水平扫描 |
2.3 解法 - 正则表达式 |
2.4 解法 - 水平扫描 |
1、题目介绍
- 难度:简单 (系统学习算法与数据结构)
- 涉及知识:字符串
- 题目编号:013
- 题目地址:https://leetcode-cn.com/problems/longest-common-prefix/
- 题目内容:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
2、解题
上面是官方使用 Java 进行的题解。
2.1 解法 - 暴力破解
解题代码:
var longestCommonPrefix = function(strs) {
if (!strs.length) {
return '';
}
let shortStrLength = strs[0].length; // 最短字符串的长度
let shortStrPosition = 0; // 最短字符串的位置
for (let i = 0; i < strs.length; i++){
if (strs[i].length < shortStrLength) {
shortStrLength = strs[i].length;
shortStrPosition = i;
}
}
let result = [];
for (let i = 0; i < shortStrLength; i++) {
for (let j = 0; j < strs.length; j++) {
if (strs[shortStrPosition][i] != strs[j][i]) {
return result.join('');
}
if (j === strs.length - 1) {
result[i] = strs[shortStrPosition][i];
}
}
}
return result.join('');
};
执行测试:
strs
:["flower","flow","flight"]
return
:
"fl"
知识点:
join()
:join()
方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。join()
详细介绍
解题思路:
-
我们进行非空判断,当它是
['']
这样子时,我们直接返回''
。 -
我们进行第一次遍历,我们需要获取到最短字符串,因为这样我们就可以进行最短的
for
遍历;我们顺带存储下位置,方便获取这个字符串。 -
我们进行双重遍历(第二/第三次遍历),将最短字符串的每个字符和其他字符串进行比对,正常情况下,我们找到不相同后,就返回结果。
-
如果我们第二/第三次遍历没有做到执行,我们返回空字符串即可。
2.2 解法 - 水平扫描
解题代码:
var longestCommonPrefix = function(strs) {
if (strs.length < 2) {
return !strs.length ? '' : strs[0];
}
var result = strs[0];
for(let i = 0; i < result.length; i++) {
for(let j = 1; j < strs.length; j++) {
if (result[i] !== strs[j][i]) {
return result.substring(0, i);
}
}
}
return result;
};
执行测试:
strs
:["flower","flow","flight"]
return
:
"fl"
知识点:
substring()
:substring()
方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。substring()
详细介绍
解题思路:
2.3 解法 - 正则表达式
解题代码:
var longestCommonPrefix = function(strs) {
if (strs.length < 2) {
return !strs.length ? '' : strs[0];
}
let base = strs.shift(),
joinStrs = '@' + strs.join('@'),
regx = '@',
res = '';
for(let i = 0; i < base.length; i++){
regx += base.substring(i, i + 1);
let matchArr = joinStrs.match(new RegExp(`${regx}`,"g")) || [];
if(matchArr.length === strs.length){
res += base.substring(i, i+1);
}
}
return res;
};
执行测试:
strs
:["flower","flow","flight"]
return
:
"fl"
知识点:
join()
:join()
方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。substring()
:substring()
方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。RegExp
:构造函数的原型对象。常用语一些便捷操作。
解题思路:
-
我们跟前两种方法一样进行空数组和数组长度为 1 时的判断。
-
我们将数组第一个字符串通过
shift()
的形式给裁剪出来。 -
我们将数组以
@
的形式拼接成字符串。因为下面我们将通过@
的形式来判断代码是否符合正则校验。 -
通过
for
循环和正则表达式判断,如果成立了,下次再判断的时候,就通过字符串拼接的形式,拓展校验规则字段regx
。 -
如果匹配返回的长度和数组总长度相等的情况下,我们就通过字符串拼接的形式修改返回值。
2.4 解法 - 水平扫描
解题代码:
var longestCommonPrefix = function(strs) {
if (strs.length < 2) {
return !strs.length ? '' : strs[0];
}
return strs.reduce((prev, next) => {
let i = 0;
while (prev[i] && next[i] && prev[i] === next[i]) {
i++;
};
return prev.slice(0, i);
});
};
执行测试:
strs
:["flower","flow","flight"]
return
:
"fl"
知识点:
reduce()
:reduce()
方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值slice()
:slice()
方法提取一个字符串的一部分,并返回一新的字符串。
解题思路:
-
这无疑是这四种思路中,写法看起来最简洁的。
-
通过
reduce()
,我们可以进行一项累加操作:先比较第一项和第二项,然后找到它们共通值后,剪切并return
;再比较的时候,使用return
出来的值和第三项进行比较……依次类推 -
返回最后一次
return
的值。