那些前端用js手搓出来的算法与数据结构(二)字符串篇

前端算法之字符串类算法

在学校时候我们用C学习数据结构时
串的结构体定义是这样的

typedef struct{
	char *ch;	//指向动态分配存储区首地址的指针 
	int length; //串的长度 
}Str;

字符串在js中是一种类型,也叫string型
直接new String 就能构造一个字符串
并且有着非常多的字符串方法index of()、slice(start, end)
substring(start, end)
substr(start, length)…
那现在总结几个字符串的算法题

1. 【面试真题】最长回文子串【双指针】

/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
if (s.length === 1) return s;
let maxRes = 0, maxStr = '';
for (let i = 0; i < s.length; i++) {
let str1 = palindrome(s, i, i);
let str2 = palindrome(s, i, i + 1);
if (str1.length > maxRes) {
maxStr = str1;
maxRes = str1.length;
}
if (str2.length > maxRes) {
maxStr = str2;
maxRes = str2.length;
}
}
return maxStr;
};
function palindrome(s, l, r) {
while (l >= 0 && r < s.length && s[l] === s[r]) {
l--;
r++;
}
return s.slice(l + 1, r);
}

2. 最长公共前缀

/**
* @param {string[]} strs
* @return {string}
*/
var longestCommonPrefix = function(strs) {
if (strs.length === 0) return "";
let first = strs[0];
if (first === "") return "";
let minLen = Number.MAX_SAFE_INTEGER;
for (let i = 1; i < strs.length; i++) {
const len = twoStrLongestCommonPrefix(first, strs[i]);
minLen = Math.min(len, minLen);
}
return first.slice(0, minLen);
};
function twoStrLongestCommonPrefix (s, t) {
let i = 0, j = 0;
let cnt = 0;
while (i < s.length && j < t.length) {
console.log(s[i], t[j], cnt)
if (s[i] === t[j]) {
cnt++;
} else {
return cnt;
}
i++;
j++;
}return cnt;
}

无重复字符的最长子串【双指针】

/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let window = {};
let left = 0, right = 0;
let maxLen = 0, maxStr = '';
while (right < s.length) {
let c = s[right];
right++;
if (window[c]) window[c]++;
else window[c] = 1
while (window[c] > 1) {
let d = s[left];
left++;
window[d]--;
}
if (maxLen < right - left) {
maxLen = right - left;
}
}
return maxLen;
};

最小覆盖子串

/**
* @param {string} s
* @param {string} t
* @return {string}
*/
var minWindow = function(s, t) {
let need = {}, window = {};
for (let c of t) {
if (!need[c]) need[c] = 1;
else need[c]++;
}
let left = 0, right = 0;
let valid = 0, len = Object.keys(need).length;
let minLen = s.length + 1, minStr = '';
while (right < s.length) {
const d = s[right];
right++;
if (!window[d]) window[d] = 1;
else window[d]++;
if (need[d] && need[d] === window[d]) {
valid++;
}
console.log('left - right', left, right);
while (valid === len) {
if (right - left < minLen) {
minLen = right - left;
minStr = s.slice(left, right);
}
console.lo
let c = s[left];
left++;
window[c]--;
if (need[c] && window[c] < need[c]) {
valid--;
}
}
}
return minStr;
};

KMP算法

求出next数组

function pmtArr(target) {
    var pmtArr = []
    target = target.split('')
    for(var j = 0; j < target.length; j++) {
    //获取模式串不同长度下的部分匹配值
        var pmt = target
        var pmtNum = 0
        for (var k = 0; k < j; k++) {
            var head = pmt.slice(0, k + 1) //前缀
            var foot = pmt.slice(j - k, j + 1) //后缀
            if (head.join('') === foot.join('')) {
                var num = head.length
                if (num > pmtNum) pmtNum = num
            }
        }
        pmtArr.push(j + 1 - pmtNum) 
    }
    return pmtArr
}

完整KMP算法

function mapKMPStr(base, target) {
    var isMatch = []
    var pmt = pmtArr(target)
    console.time('kmp')
    var times = 0
    for(var i = 0; i < base.length; i++) {
        times++
        var tempIndex = 0
        for(var j = 0; j < target.length; j++) {
            if(i + target.length <= base.length) {
                if (target.charAt(j) === base.charAt(i + j)) {
                    isMatch.push(target.charAt(j))
                } else {
                    if(!j) break //第一个就不匹配直接跳到下一个
                    var skip = pmt[j - 1]
                    tempIndex = i + skip - 1
                    break 
                }
            }
        }
        var data = {
            index: i,
            matchArr: isMatch
        }
        callerKmp.push(data)
        if(tempIndex) i = tempIndex
        if(isMatch.length === target.length) {
            console.timeEnd('kmp')
            console.log('移位次数:', times)
            return i
        }
        isMatch = []
    }
    console.timeEnd('kmp')
    return -1

kmp算法相关链接

KMP算法参考
KMP算法参考二
阮一峰博客
nextval简单讲解

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值