《数据结构与算法JavaScript描述》栈(学习笔记C04)

本文深入解析栈数据结构的概念、操作及实现,并通过力扣(LeetCode)平台的典型题目,如括号匹配、下一个更大元素和删除最外层括号,展示栈的应用技巧。

相关概念

1.栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶。
2.栈被称为一种后入先出(LIFO,last-in-first-out)的数据结构。
3.入栈使用 push() 方法,出栈使用 pop() 方法,peek() 方法则只返回栈顶元素(预览栈顶元素不删除)。

代码

// 栈的实现
// 常规操作: 
// 压入栈 push()
// 弹出栈 pop()
// 预览栈顶 peek()
// 顶元素位置 变量 top
// 清除栈内所有元素 clear()
// 记录栈内元素个数 length
// 表示栈内是否含有元素 empty
// 底层实现结构--数组

// 定义Stack类的构造函数
function Stack() {
    this.dataStore = []
    this.top = 0
    this.push = push
    this.pop = pop
    this.peek = peek
    this.clear = clear
    this.length = length
}    
// push()
function push(element) {
    this.dataStore[this.top++] = element
}
// pop()
function pop() {
    return this.dataStore[--this.top]
}
// peek()
function peek() {
    return this.dataStore[this.top-1]
}
// length()
function length() {
    return this.top
}
// clear()
function clear() {
    this.top = 0
}
// 测试
var s = new Stack()
s.push('xx1')
s.push('xx2')
s.push('xx3')
console.log('length: ' + s.length())
console.log('s.peek()' + s.peek())
var popped = s.pop()
console.log('The popped element is: ' + popped)
console.log('s.peek()' + s.peek())
s.push('xx4')
console.log('s.peek()', s.peek())
s.clear()
console.log('length: ',s.length())
console.log('s.peek()', s.peek())
s.push('xx5')
console.log(s.peek())
 
// 使用栈解决问题

// 1.数制间的相互转换

function mulBase(num, base) {
    var s = new Stack()
    do {
        s.push(num % base)
        num = Math.floor(num /= base)
    } while (num > 0)
    var converted = ''
    while (s.length() > 0) {
        converted += s.pop()
    }
    return converted
}
// 1.1转二进制
var num = 32
var base = 2
var newNum = mulBase(num, base)
// console.log(num + ' converted to base ' + base + ' is ' + newNum)
// 1.2转八进制
num = 125
base = 8
var newNum = mulBase(num, base)
// console.log(num + ' converted to base ' + base + ' is ' + newNum)

// 2.回文
function isPalindrome(word) {
    var s = new Stack()
    for (var i = 0; i < word.length; ++i) {
        s.push(word[i])
    }
    var rword = ''
    while (s.length() > 0) {
        rword += s.pop()
    }
    if (word == rword) {
        return true
    } else {
        return false
    }
}

var word = 'hello'
if (isPalindrome(word)) {
     console.log(word + ' is a palindrome.')
} else {
     console.log(word + ' is not a palindrome')
}
var word = 'racecar'
if (isPalindrome(word)) {
     console.log(word + ' is a palindrome.')
} else {
     console.log(word + ' is not a palindrome')
}

// 递归工作原理:http://bit.ly/lenDGE3

// 3.阶乘递归
function facorial(n) {
    if (n === 0) {
        return 1
    } else {
        return n*facorial(n-1)
    }
}
var num1 = facorial(5)
console.log('递归一', num1)
function fact(n) {
    var s = new Stack()
    while (n > 1) {
        s.push(n--)
    }
    var product = 1
    while (s.length() > 0) {
        product *= s.pop()
    }
    return product
}
var num2 = fact(5)
console.log('递归二', num2)

力扣相关题目

以下题目难度全部为简单:

1.1题目描述:

  1. 有效的括号
    给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
    有效字符串需满足:
    1.左括号必须用相同类型的右括号闭合。
    2.左括号必须以正确的顺序闭合。
    注意:空字符串可被认为是有效字符串。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses

1.2.我的解答

/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
	// 思路:原数组与空数组(相当于将原数组对折与新数组比较)
	var s = s.split('')
	var arr = []
	for(var i=0; i<s.length; i++){
	    if(s[i] === '('){
	        arr.push(')')
	    }else if(s[i] === '['){
	        arr.push(']')
	    }else if(s[i] === '{'){
	        arr.push('}')
	    }else if(arr.pop() !== s[i]){
	        return false
	    }
	}
	if(arr.length){
	    return false
	}else{
	    return true
	}
};

2.1.题目描述:

  1. 下一个更大元素 I
    给定两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
    nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

2.2.示例:

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/next-greater-element-i。

2.3.我的解答:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var nextGreaterElement = function(nums1, nums2) {
    var arr = []
    for(var i=0; i<nums1.length; i++){
         var index = nums2.indexOf(nums1[i])+1
         var arrIn = []
         for(var j=index; j<nums2.length; j++){
             if(nums2[j]>nums1[i]){
                 arrIn.push(nums2[j])
             }
         }
         if(arrIn.length>0){
             arr.push(arrIn[0])
         }else{
             arr.push(-1)
         }
    }
    return arr 
};

3.1.题目描述:

  1. 删除最外层的括号
    有效括号字符串为空 ("")、"(" + A + “)” 或 A + B,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。例如,"","()","(())()" 和 “(()(()))” 都是有效的括号字符串。
    如果有效字符串 S 非空,且不存在将其拆分为 S = A+B 的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。
    给出一个非空有效字符串 S,考虑将其进行原语化分解,使得:S = P_1 + P_2 + … + P_k,其中 P_i 是有效括号字符串原语。
    对 S 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 S 。

3.2.示例:

输入:"(()())(())"
输出:"()()()"
输入:"()()"
输出:""

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-outermost-parentheses

3.3.我的解答:

/**
 * @param {string} S
 * @return {string}
 */
var removeOuterParentheses = function(S) {
    // 从 0 开始计数,遇 a 则 +1 遇 b 则 -1 
    // 当 a=1 且 b=0 就为最外层括号,记下序号
    var arr = S.split('')
    var indexArrB = []
    var count = 0
    for (var i=0; i<arr.length; i++) {
        if (arr[i] == '(') {
           count++ 
        } else {
           count--  
        }
        if(count==0){
            indexArrB.push(i)
        }
    }
    // console.log('序号数组其一--',indexArrB)
    // 需要删除的元素序号
    var indexArrA = []
    for(var i=0; i<indexArrB.length-1; i++) {
        indexArrA.push(indexArrB[i]+1)
    }
    indexArrA.unshift(0)
    // console.log('有序数组其二',indexArrA)
    var index = indexArrA.concat(indexArrB)

    var indexArr = []
    for(var i=0; i<arr.length; i++){
        if(index.indexOf(i) == -1) {
            indexArr.push(arr[i])
        }
    }
    return indexArr.join('')
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值