前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Js算法与数据结构拾萃(2)

Js算法与数据结构拾萃(2)

作者头像
一粒小麦
发布2020-02-25 10:07:13
4860
发布2020-02-25 10:07:13
举报
文章被收录于专栏:一Li小麦一Li小麦
关于栈

补白

准备阅读: 《javascript数据结构和算法》读书笔记:[1]

这是笔者一年前的笔记。在此文中,我们无非是说明了栈的特征:先进后出,后进先出。

尝试使用JavaScript创建一个栈(stack):

class Stack{
    constructor(array=[]){
        this.array=array;
    }
    // 入栈
    push(item){
        this.array.push(item);
    }
    // 出栈并返回出栈元素
    pop(){
        return this.array.pop();
    }
    // 查看栈顶
    peek(){
        return this.array[this.array.length-1];
    }
    // 是否为空
    isEmpty(){
        return this.array.length==0;
    }
    // 清栈
    clear(){
        this.array=[];
    }
    // 返回栈元素个数
    size(){
        return this.array.length;
    }
    // 打印
    print(){
        console.log(this.array)
    }
}

【案例1】有效的括号

对应leetcode第20题 难度:简单 https://leetcode.com/problems/valid-parentheses/

Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

An input string is valid if:

•Open brackets must be closed by the same type of brackets.•Open brackets must be closed in the correct order.•Note that an empty string is also considered valid.

# Example 1:
Input: "()"
Output: true

# Example 2:
Input: "()[]{}"
Output: true

# Example 3:
Input: "(]"
Output: false

# Example 4:
Input: "([)]"
Output: false

# Example 5:
Input: "{[]}"
Output: true
题解:运用栈来解决问题

考虑遍历此字符串,每次遍历做如下判断:

•如果是左开头,入栈•否则:•如果栈不为空,返回false•否则判断栈顶和当前字符是否配对,配对则出栈,不配对则入栈

最后返回的栈是否为空。

/**
 * @param {string} s
 * @return {boolean}
 */

// Stack
const isValid =  (s) => {
    const stack=new Stack([]);
    // 定义字典
    const isCouple=(l,r)=>{
        if((l=='('&&r==')')||(l=='['&&r==']')||(l=='{'&&r=='}')){
            return true;
        }
        return false
    }

    for(let i=0;i<s.length;i++){
        if(s[i]=='('||s[i]=='['||s[i]=='{'){
            stack.push(s[i]);
        }else{
            if(stack.isEmpty()){
                return false;
            }else{
                if(isCouple(stack.peek(),s[i])){
                    stack.pop();
                }else{
                    stack.push(s[i]);
                }            }
        }
    }

    return stack.isEmpty();

};
变化图

运行效率还有可以调优的地方。主要在于减少无谓的if else判读。

如果不显式声明栈,这种方法来判断或是比较优雅很多

const isValid = (s) => {
    const stack = [];
    // 定义字典
    const couple = {
        '(': ')',
        '[': ']',
        '{': '}'
    }

    for (let i = 0; i < s.length; i++) {
        if (s[i] in couple) {
            stack.push(s[i]);
        } else {
            if (couple[stack.pop()]!=s[i]) {
                return false;
            }
        }
    }

    return !stack.length;
};

【案例2】简单路径

对应leetcode 71题 难度:中等 https://leetcode.com/problems/simplify-path/

Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path.

In a UNIX-style file system, a period . refers to the current directory. Furthermore, a double period .. moves the directory up a level. For more information, see: Absolute path vs relative path in Linux/Unix[2]

Note that the returned canonical path must always begin with a slash /, and there must be only a single slash / between two directory names. The last directory name (if it exists) must not end with a trailing /. Also, the canonical path must be the shortest string representing the absolute path.

以 Unix 风格给出一个文件的绝对路径,简化它——也就是说,将其转换为规范路径。

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。

请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能/ 结尾。此外,规范路径必须是表示绝对路径的最短字符串。

示例 1:

输入:"/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。

示例 2:

输入:"/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。

示例 3:

输入:"/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。

示例 4:

输入:"/a/./b/../../c/"
输出:"/c"

示例 5:

输入:"/a/../../b/../c//.//"
输出:"/c"

示例 6:

输入:"/a//b////c/d//././/.."
输出:"/a/b/c"

经常用nodeJs的话,会对unix路径比较熟悉。简单说:

/开头代表跟路径•../..表示当前目录向上•./表示当前目录

在node环境下,可以使用

const path = require('path');
const simplifyPath = (path) => {
    return Path.resolve(path)
};

但是测试环境并不支持node,需要你自己来做。

题解

先把字符用/生成数组考虑出栈和入栈的时机。..表示向上,.和空字符串都不操作。其它入栈即可。

/**
 * @param {string} path
 * @return {string}
 */
const simplifyPath = (path) => {

    let pathArr = path.split('/');

    const stack = [];
    for (let i = 0; i < pathArr.length; i++) {
        switch (pathArr[i]) {
            case '..':
                // 向上一级
                if (stack.length!=0) {
                    stack.pop();
                }
                break;
            case '.':
                // 当前目录
            case '':
                break;
            default:
                stack.push(pathArr[i].replace(/\//g,''))
                break;
        }
    }
    return '/'+stack.join('/');

};

References

[1] 《javascript数据结构和算法》读书笔记:栈: http://mp.weixin.qq.com/s?__biz=MzIxMDQ2NjUwNg==&mid=2247483810&idx=1&sn=40d27b7c8e20b9820f69022e9ccc3ee4&chksm=97656207a012eb11e276094cd6c8cd8b2fdca9eb80a4ba00c16ede69b58e2a30bc3ce29b2c0a&token=1334209442&lang=zh_CN#rd [2] Absolute path vs relative path in Linux/Unix: https://www.linuxnix.com/abslute-path-vs-relative-path-in-linuxunix/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一Li小麦 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 补白
  • 【案例1】有效的括号
    • 题解:运用栈来解决问题
      • 变化图
      • 【案例2】简单路径
        • 题解
        • References
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档