字符串操作&栈和队列

反转字符串II

javascript 复制代码
/**
 * @param {string} s
 * @param {number} k
 * @return {string}
 */
var reverseStr = function(s, k) {
    // //字符串=》字符数组
    // let sArr=s.split('');
    // let length=s.length;
    // //每计数2*k for!!!
    // for(let i=0;i<length;i+=2*k){
    //     let left=i;
    //     //right指向要反转的最后字符们不要mid!
    //     //三元表达式,判断i+k-1右边的指针是否超过字符长度(2k与2k>=k),没超过就是交换前k
    //     //超过标识字符小于k,就全交换剩下的字符
    //     let right=(i+k-1)>=length?length-1:i+k-1;
    //     while(left<right){
    //         [sArr[left],sArr[right]]=[sArr[right],sArr[left]];
    //         left++;
    //         right--;
    //     }
    // }

    const reverse=(arr,left,right)=>{
        while(left<right){
            [arr[left],arr[right]]=[arr[right],arr[left]];
            left++;right--;
        }
    }

    //核心是模拟,无需讨论情况,每次跳2k,并判断(当前位置+k)是否越界

    let arr=s.split('');
    //2*k不是2k
    for(let i=0;i<s.length;i+=2*k){
        //如果剩余元素大于k/有2k个元素
        if(i+k-1<s.length){
            reverse(arr,i,i+k-1);
        }else{
            reverse(arr,i,s.length);
        }
    }
    return arr.join(''); 
};

翻转字符串中的单词

javascript 复制代码
/**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function(s) {

   /**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function(s) {


    
    //推荐
    let wordArr=s.split(" ");
    let filtered=wordArr.filter(item=>item!=="");
    let length=filtered.length;
    let right=length-1;
    for(let left=0;left<length;left++){
        if(left>=right){
            break;
        }
        [filtered[left],filtered[right]]=[filtered[right],filtered[left]];
        right--;
    }
    return filtered.join(" ");



    // //字符数组
    // let charArr=Array.from(s);

    //  var removeBlank=(arr)=>{
    //     let left=0;
    //     for(let right=0;right<arr.length;right++){
    //         //为最前面有空格或连续空格
    //         if(arr[right]===" "&&(right===0||arr[right-1]===" "))continue;
    //         else{
    //             arr[left]=arr[right];
    //             left++;
    //         }
    //     }
    //     //考虑到移除尾部单个空格
    //     //因为执行赋值后有left++了,所以此处要再减1
    //     arr.length=arr[left-1]===" "?left-1:left;//此处求的是长度,slow指针索引,从0开始
    // }

    // //移除空格
    // removeBlank(charArr);

    // // //思路:去除空格,去除对于空格(双指针)
    // // //反转全部->反转每个单词
    // var reverse=(arr,left,right)=>{
    //     while(left<right){
    //         [arr[left],arr[right]]=[arr[right],arr[left]];
    //         left++;
    //         right--;
    //     }
    // }
    // // //反转全部
    // reverse(charArr,0,charArr.length-1);
    
    // // //反转每个单词
    // // 没遇到空格就是一个新单词或者到结尾
    // let left=0;
    // let right=0;
    //  //right===charArr.length是right-1才是最后一位
    // for(;right<=charArr.length;right++ ){
    //     //right===charArr.length是right-1才是最后一位
    //     if((charArr[right]===" ")|| (right===charArr.length)){
    //         reverse(charArr,left,right-1);
    //         left=right+1;
    //     }
    // }

    //return charArr.join(''); 
}
}

KMP经典应用

next初始化-> 前后缀不相同(回退,next数组)->前后缀相同->j加入next数组

初始化,获取next数组->前后缀不相同(回退,next数组)->前后缀相同->到末尾

javascript 复制代码
/**
 * @param {string} haystack
 * @param {string} needle
 * @return {number}
 */
var strStr = function(haystack, needle) {

    if(needle.length===0)return 0;
    let next=getNext(needle);
    let j=0;
        for(let i=0;i<haystack.length;i++){
        //字符匹配到不同的,回溯跳!!!while
        while(j>0 && haystack[i]!==needle[j]){
            j=next[j-1];//写成need[j-1],excuse me?
        }
        //相等时,继续往下匹配
        if(haystack[i]===needle[j]){
            j++;
        }
        //匹配成功,i此时仍指向最后一字符
        //气死,length写出lenth,死都找不到那出错了
        if(j===needle.length){
            return i-needle.length+1;
        }
    }
    //未找到
    return -1;

};

var getNext=function(needle){
    //初始化
    let next=[];
    let j=0;
    next.push(j);
    //双指针!
    for(let i=1;i<needle.length;i++){
        //前后缀不同,循环回溯
        while(j>0&&needle[i]!==needle[j]){
            j=next[j-1];
        }
        if(needle[i]===needle[j]){
            j++;
        }
        next.push(j);
    }
    //记得返回出去!!!
    return next;
}

重复的字子字符串(能用KMP!前后缀)

结论:保证next大于0,即有最长前后缀,子串中除去最长前后缀其他部分为最小重复字符串
除去这个最长相等的前缀和后缀剩下的部分(即重复的子串)是否能整除整个字符串的长度。如果可以整除,说明 s 是由这个更小的字符串重复构成的。

javascript 复制代码
/**
 * @param {string} s
 * @return {boolean}
 */
var repeatedSubstringPattern = function(s) {
    let next=getNext(s);
    //保证next大于0,即有最长前后缀,子串中除去最长前后缀的其他部分为最小重复字符串
    //next[next.length-1] 表示整个字符串 s 的最长相等的前缀和后缀的长度。
    //s.length % (s.length - next[next.length-1]) === 0 用于判断,除去这个最长相等的前缀和后缀
    //剩下的部分(即重复的子串)是否能整除整个字符串的长度。如果可以整除,说明 s 是由这个更小的字符串重复构成的。
    if(next[next.length-1]>0&&s.length%(s.length-next[next.length-1])===0)return true;
    return false;
};
var getNext=function(s){
    //初始化
    let j=0;
    let next=[];
    next.push(j);
    for(let i=1;i<s.length;i++){
        //前后缀不相同
        while(j>0&&s[i]!==s[j]){
            //回溯
            j=next[j-1];
        }
        //前后缀相同时
        if(s[i]===s[j]) j++;
        //更新next数组
        next.push(j);
    }
    return next;
}

有效的括号

javascript 复制代码
/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    // let stack=[];

    // for(let i=0;i<s.length;i++){
    //     let cur=s[i];
    //     switch(cur){
    //         case "{":
    //             stack.push("}");
    //             break;
    //         case "(":
    //             stack.push(")");
    //             break;
    //         case "[":
    //             stack.push("]");
    //             break;
    //         default:
    //             let flag=stack.pop()===cur;
    //             if(!flag)return false;
    //     }
    // }
    // return stack.length===0;

    const stack = [];
    //键值对
    let  obj1  = {
            "(":")",
            "{":"}",
            "[":"]"
        };
    for(const x of s) {
        if(x in obj1) {
            //遇到左括号将对应右括号加入栈
            stack.push(obj1[x]);
            //跳出本次循环
            continue;
        };
        //遇到右括号从栈中弹出数据,若不同就返回false
        if(stack.pop() !== x) return false;
    }
    //若还剩数据也不行!!!
    return !stack.length;

};

删除字符串中的所有相邻重复项

javascript 复制代码
/**
 * @param {string} s
 * @return {string}
 */
var removeDuplicates = function(s) {
    //初始化空栈
    let stack=[];
    for(let i=0;i<s.length;i++){
        let cur=s[i];
        //判断栈是否为空
        if(stack.length>0){
            //不为空,将当前数据和栈顶数据比较
            let top=stack[stack.length-1]
            if(top===cur){
                //相同就弹出
                stack.pop();
            }else{
                //不相同就将此数据继续加入栈中
                stack.push(cur);
            }
        }else{
            //当栈中没数据就加入
            stack.push(cur);
        }
    }
    return stack.join("");


};

逆波兰表达式求值

javascript 复制代码
/**
 * @param {string[]} tokens
 * @return {number}
 */
var evalRPN = function(tokens) {

    //思路:初始化一个栈,遇到数字就将数字压入栈中
    //遇到符号就从栈中弹出两个数字,弹出的数字的顺序matters!!!
    //然后再将结果压入栈,直至处理完成
    const stack = [];
    for (const token of tokens) {
        if (isNaN(Number(token))) { // 非数字
            const n2 = stack.pop(); // 出栈两个数字
            const n1 = stack.pop();
            switch (token) { // 判断运算符类型,算出新数入栈
                case "+":
                    stack.push(n1 + n2);
                    break;
                case "-":
                    stack.push(n1 - n2);
                    break;
                case "*":
                    stack.push(n1 * n2);
                    break;
                case "/":
                    stack.push(n1 / n2 | 0);
                    break;
            }
        } else { // 数字
            stack.push(Number(token));
        }
    }
    return stack[0]; // 因没有遇到运算符而待在栈中的结果
};

滑动窗口最大值★★★

前K个高频元素★★

大小堆原理详解

相关推荐
Moment几秒前
拆包的艺术:Webpack SplitChunksPlugin 执行流程全流程揭秘 🤩🤩🤩
前端·javascript·webpack
0xJohnsoy2 分钟前
Javascript中的函数柯里化
前端
那小孩儿2 分钟前
最简单的new Date()展示,也能做优化
前端·javascript·性能优化
pink大呲花4 分钟前
Vue.js 中 v-if 的使用及其原理
前端·javascript·vue.js
叶小秋6 分钟前
Next.js + Tailwind CSS 移动端适配方案
前端·next.js
北京_宏哥6 分钟前
🔥PC端自动化测试实战教程-4-pywinauto 操作PC端应用程序窗口 - 上篇(详细教程)
前端·python·测试
北京_宏哥8 分钟前
🔥PC端自动化测试实战教程-3-pywinauto 启动PC端应用程序 - 下篇(详细教程)
前端·windows·python
天官赐福_32 分钟前
vue2的scale方式适配大屏
前端·vue.js
江城开朗的豌豆32 分钟前
CSS篇:前端经典布局方案:左侧固定右侧自适应的6种实现方式
前端·css·面试
Carlos_sam34 分钟前
Openlayers:flat样式介绍
javascript