栈的理解
栈是一种高效的数据结构,因为数据只能在栈顶添加或删除,所以这样的操作很快,而且容易实现。栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶。栈被称为一种后入先出(LIFO,last-in-first-out)的数据结构。由于栈具有后入先出的特点,所以任何不在栈顶的元素都无法访问。为了得到栈底的元 素,必须先拿掉上面的元素。
栈的封装
function Stack() {
// 属性
this.items = [];
// 方法
// 1将元素加入栈中
Stack.prototype.push = function (elment) {
this.items.push(elment);
}
// 2从栈中取元素
Stack.prototype.pop = function () {
this.items.pop();
}
// 3 查看栈顶(底)元素
Stack.prototype.peek = function () {
return this.items[this.items.length - 1];
}
// 4 队列是否为空
Stack.prototype.isEmpty = function () {
return this.items === 0;
}
// 5查看队列中的元素个数
Stack.prototype.size = function () {
return this.items.length;
}
// 6 toString方法
Stack.prototype.toString = function () {
let res = '';
for (let i = 0; i < this.items.length; i++) {
res += this.items[i] + ' ';
}
return res;
}
}
let s = new Stack()
s.push(1);
s.push(10);
s.push(100);
s.push(1000);
// console.log(s) // [1, 10, 100, 1000]
s.pop()
// console.log(s) // [1, 10, 100]
alert(s.peek()) // 100
alert(s.toString()) // 1 10 100
应用- 将十进制数转二进制
// 将十进制数转二进制
function toBinaryNumber(number) {
// 1 将取模的数推入栈
let stack = [];
// 获取每次除以2的整数结果 大于0就继续循环
while (number > 0) {
stack.push(number % 2);
number = Math.floor(number / 2);
}
// 返回字符串结果 -反转
let res = stack.reverse().join('')
return res
}
let t = toBinaryNumber(100)
console.log(t) // 1100100
<p> 100 ---> 二进制 ---> 1100100</p>
<p> 100 % 2 -> 0 --->栈底</p>
<p> 50 % 2 -> 0</p>
<p> 25 % 2 -> 1</p>
<p> 12 % 2 -> 0</p>
<p> 6 % 2 -> 0</p>
<p> 3 % 2 -> 1</p>
<p> 1 % 2 -> 1 ---> 栈顶</p>
<p> 结果是从下往上 1100100</p>
应用-旋转数组k次
/**
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
*/
// 0(n^2)
var rotate2 = function (nums, k) {
const length = nums.length;
if (length === 0 || !k) return nums;
for(let i=0;i<k;i++) {
let n = nums.pop();
if(n != null) { // 注意元素为0的时候 if(0)
nums.unshift(n) // 数组是一个有序结构,unshift操作非常慢 O(n)
}
}
return nums;
};
let arr2 = [1, 2, 3, 4, 5, 6, 0]
let l2 = rotate2(arr2, 3)
console.log(l2) // [5,6,0,1,2,3,4]
// O(n)
var rotate1 = function (nums, k) {
const length = nums.length;
if (length === 0 || !k) return nums;
const step = Math.abs(k % length)
let arr1 = nums.slice(-step)
let arr2 = nums.slice(0, length - step);
let arr3 = arr1.concat(arr2);
return arr3
};
let arr = [1, 2, 3, 4, 5, 6, 7]
let l = rotate1(arr, 3)
console.log(l) // [5,6,7,1,2,3,4]
应用- 有效的括号
var checkValid = function (left, right) {
if (left === '(' && right === ')') return true;
if (left === '{' && right === '}') return true;
if (left === '[' && right === ']') return true;
return false
}
var isValid = function (s) {
const length = s.length;
if (length % 2 === 1) return false; // 括号成对出现,是偶数
let stack = [];
let leftSmbols = '([{';
let rightSmbols = ')]}';
for (let i = 0; i < length; i++) {
const str = s[i];
if (leftSmbols.includes(str)) {
stack.push(str) // 入栈
} else if (rightSmbols.includes(str)) {
let lastStr = stack[stack.length - 1]; // 最后一位来判断 后进先出一一对应
if (checkValid(lastStr, str)) {
stack.pop() // 出栈 后进先出
} else {
return false
}
}
}
return stack.length === 0;
}
let s = '({([{}])})';
console.log(isValid(s))