当前位置: 首页 > article >正文

Javascript数据结构常见题目(一)

以下是每个问题的 JavaScript 实现:


1. 下一个更大元素 (循环数组)

function nextGreaterElements(nums) {
    let n = nums.length;
    let result = Array(n).fill(-1);
    let stack = [];
    for (let i = 0; i < 2 * n; i++) {
        let num = nums[i % n];
        while (stack.length && nums[stack[stack.length - 1]] < num) {
            result[stack.pop()] = num;
        }
        if (i < n) stack.push(i);
    }
    return result;
}

2. 逆波兰表达式求值

function evalRPN(tokens) {
    let stack = [];
    for (let token of tokens) {
        if (!isNaN(token)) {
            stack.push(Number(token));
        } else {
            let b = stack.pop();
            let a = stack.pop();
            switch (token) {
                case '+': stack.push(a + b); break;
                case '-': stack.push(a - b); break;
                case '*': stack.push(a * b); break;
                case '/': stack.push(Math.trunc(a / b)); break;
            }
        }
    }
    return stack[0];
}

3. 二叉树的最大路径和

function maxPathSum(root) {
    let maxSum = -Infinity;

    function dfs(node) {
        if (!node) return 0;
        let left = Math.max(0, dfs(node.left));
        let right = Math.max(0, dfs(node.right));
        maxSum = Math.max(maxSum, left + right + node.val);
        return Math.max(left, right) + node.val;
    }

    dfs(root);
    return maxSum;
}

4. 从前序与中序遍历序列构造二叉树

function buildTree(preorder, inorder) {
    if (!preorder.length || !inorder.length) return null;

    let rootVal = preorder[0];
    let root = { val: rootVal, left: null, right: null };
    let mid = inorder.indexOf(rootVal);

    root.left = buildTree(preorder.slice(1, mid + 1), inorder.slice(0, mid));
    root.right = buildTree(preorder.slice(mid + 1), inorder.slice(mid + 1));
    return root;
}

5. 从中序与后序遍历序列构造二叉树

function buildTreeFromInPost(inorder, postorder) {
    if (!inorder.length || !postorder.length) return null;

    let rootVal = postorder.pop();
    let root = { val: rootVal, left: null, right: null };
    let mid = inorder.indexOf(rootVal);

    root.right = buildTreeFromInPost(inorder.slice(mid + 1), postorder);
    root.left = buildTreeFromInPost(inorder.slice(0, mid), postorder);
    return root;
}

6. 栈的链式存储

class StackNode {
    constructor(value) {
        this.value = value;
        this.next = null;
    }
}

class LinkedStack {
    constructor() {
        this.top = null;
    }

    push(value) {
        let newNode = new StackNode(value);
        newNode.next = this.top;
        this.top = newNode;
    }

    pop() {
        if (!this.top) return null;
        let value = this.top.value;
        this.top = this.top.next;
        return value;
    }

    peek() {
        return this.top ? this.top.value : null;
    }

    isEmpty() {
        return this.top === null;
    }
}

7. 下一个更大元素

function nextGreaterElement(nums1, nums2) {
    let map = new Map();
    let stack = [];

    for (let num of nums2) {
        while (stack.length && stack[stack.length - 1] < num) {
            map.set(stack.pop(), num);
        }
        stack.push(num);
    }

    return nums1.map(num => map.get(num) || -1);
}

8. 括号匹配

function isValid(s) {
    let stack = [];
    let map = { ')': '(', '}': '{', ']': '[' };

    for (let char of s) {
        if (char in map) {
            if (stack.pop() !== map[char]) return false;
        } else {
            stack.push(char);
        }
    }

    return stack.length === 0;
}

9. 二叉树的最近公共祖先

function lowestCommonAncestor(root, p, q) {
    if (!root || root === p || root === q) return root;

    let left = lowestCommonAncestor(root.left, p, q);
    let right = lowestCommonAncestor(root.right, p, q);

    if (left && right) return root;
    return left || right;
}

这些代码覆盖了您所列的所有问题,且在实践中非常实用。希望对您有所帮助!
以下是每个问题的 JavaScript 实现:


1. 最小栈

class MinStack {
    constructor() {
        this.stack = [];
        this.minStack = [];
    }

    push(val) {
        this.stack.push(val);
        if (!this.minStack.length || val <= this.getMin()) {
            this.minStack.push(val);
        }
    }

    pop() {
        if (this.stack.pop() === this.getMin()) {
            this.minStack.pop();
        }
    }

    top() {
        return this.stack[this.stack.length - 1];
    }

    getMin() {
        return this.minStack[this.minStack.length - 1];
    }
}

2. 用栈实现队列

class MyQueue {
    constructor() {
        this.stackIn = [];
        this.stackOut = [];
    }

    push(x) {
        this.stackIn.push(x);
    }

    pop() {
        this._move();
        return this.stackOut.pop();
    }

    peek() {
        this._move();
        return this.stackOut[this.stackOut.length - 1];
    }

    empty() {
        return !this.stackIn.length && !this.stackOut.length;
    }

    _move() {
        if (!this.stackOut.length) {
            while (this.stackIn.length) {
                this.stackOut.push(this.stackIn.pop());
            }
        }
    }
}

3. 二叉树的右视图

function rightSideView(root) {
    if (!root) return [];
    let result = [];
    let queue = [root];

    while (queue.length) {
        let levelSize = queue.length;
        for (let i = 0; i < levelSize; i++) {
            let node = queue.shift();
            if (i === levelSize - 1) result.push(node.val);
            if (node.left) queue.push(node.left);
            if (node.right) queue.push(node.right);
        }
    }
    return result;
}

4. 表达式求值

function evaluateExpression(expression) {
    let stack = [];
    let num = 0;
    let sign = 1;
    let result = 0;

    for (let char of expression) {
        if (char === ' ') continue;
        if (/\d/.test(char)) {
            num = num * 10 + Number(char);
        } else if (char === '+') {
            result += sign * num;
            num = 0;
            sign = 1;
        } else if (char === '-') {
            result += sign * num;
            num = 0;
            sign = -1;
        } else if (char === '(') {
            stack.push(result);
            stack.push(sign);
            result = 0;
            sign = 1;
        } else if (char === ')') {
            result += sign * num;
            num = 0;
            result *= stack.pop();
            result += stack.pop();
        }
    }
    return result + sign * num;
}

5. 验证二叉搜索树

function isValidBST(root, min = null, max = null) {
    if (!root) return true;
    if ((min !== null && root.val <= min) || (max !== null && root.val >= max)) {
        return false;
    }
    return isValidBST(root.left, min, root.val) && isValidBST(root.right, root.val, max);
}

6. 用队列实现栈

class MyStack {
    constructor() {
        this.queue = [];
    }

    push(x) {
        this.queue.push(x);
        let size = this.queue.length;
        while (size > 1) {
            this.queue.push(this.queue.shift());
            size--;
        }
    }

    pop() {
        return this.queue.shift();
    }

    top() {
        return this.queue[0];
    }

    empty() {
        return !this.queue.length;
    }
}

7. 二叉树的序列化与反序列化

class Codec {
    serialize(root) {
        if (!root) return 'null';
        return `${root.val},${this.serialize(root.left)},${this.serialize(root.right)}`;
    }

    deserialize(data) {
        let nodes = data.split(',');
        function buildTree() {
            let val = nodes.shift();
            if (val === 'null') return null;
            let node = { val: Number(val), left: null, right: null };
            node.left = buildTree();
            node.right = buildTree();
            return node;
        }
        return buildTree();
    }
}

8. 二叉树的最大深度

function maxDepth(root) {
    if (!root) return 0;
    return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}

9. 二叉树的最小深度

function minDepth(root) {
    if (!root) return 0;
    if (!root.left) return 1 + minDepth(root.right);
    if (!root.right) return 1 + minDepth(root.left);
    return 1 + Math.min(minDepth(root.left), minDepth(root.right));
}

10. 路径总和

function hasPathSum(root, targetSum) {
    if (!root) return false;
    if (!root.left && !root.right) return root.val === targetSum;
    return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}

这些实现涵盖了问题的核心逻辑,旨在高效地解决每个场景的问题。希望这些代码对您有帮助!
以下是每个问题的 JavaScript 解决方案:


1. 对称二叉树

function isSymmetric(root) {
    function isMirror(t1, t2) {
        if (!t1 && !t2) return true;
        if (!t1 || !t2) return false;
        return t1.val === t2.val && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left);
    }
    return isMirror(root, root);
}

2. 二叉树的中序遍历

function inorderTraversal(root) {
    let result = [];
    function traverse(node) {
        if (!node) return;
        traverse(node.left);
        result.push(node.val);
        traverse(node.right);
    }
    traverse(root);
    return result;
}

3. 二叉树的层序遍历

function levelOrder(root) {
    if (!root) return [];
    let result = [];
    let queue = [root];

    while (queue.length) {
        let level = [];
        let size = queue.length;
        for (let i = 0; i < size; i++) {
            let node = queue.shift();
            level.push(node.val);
            if (node.left) queue.push(node.left);
            if (node.right) queue.push(node.right);
        }
        result.push(level);
    }
    return result;
}

4. 二叉树的直径

function diameterOfBinaryTree(root) {
    let diameter = 0;

    function depth(node) {
        if (!node) return 0;
        let left = depth(node.left);
        let right = depth(node.right);
        diameter = Math.max(diameter, left + right);
        return 1 + Math.max(left, right);
    }

    depth(root);
    return diameter;
}

5. 二叉树的前序遍历

function preorderTraversal(root) {
    let result = [];
    function traverse(node) {
        if (!node) return;
        result.push(node.val);
        traverse(node.left);
        traverse(node.right);
    }
    traverse(root);
    return result;
}

6. 二叉树的后序遍历

function postorderTraversal(root) {
    let result = [];
    function traverse(node) {
        if (!node) return;
        traverse(node.left);
        traverse(node.right);
        result.push(node.val);
    }
    traverse(root);
    return result;
}

7. 翻转二叉树

function invertTree(root) {
    if (!root) return null;
    [root.left, root.right] = [invertTree(root.right), invertTree(root.left)];
    return root;
}

8. 二叉树的所有路径

function binaryTreePaths(root) {
    let paths = [];
    function constructPaths(node, path) {
        if (node) {
            path += node.val;
            if (!node.left && !node.right) {
                paths.push(path);
            } else {
                path += '->';
                constructPaths(node.left, path);
                constructPaths(node.right, path);
            }
        }
    }
    constructPaths(root, '');
    return paths;
}

9. 二又树的中序遍历(非递归)

function inorderTraversalIterative(root) {
    let result = [];
    let stack = [];
    let current = root;

    while (current || stack.length) {
        while (current) {
            stack.push(current);
            current = current.left;
        }
        current = stack.pop();
        result.push(current.val);
        current = current.right;
    }

    return result;
}

10. 二分图检测

function isBipartite(graph) {
    let colors = Array(graph.length).fill(0);

    function dfs(node, color) {
        if (colors[node] !== 0) return colors[node] === color;
        colors[node] = color;

        for (let neighbor of graph[node]) {
            if (!dfs(neighbor, -color)) return false;
        }
        return true;
    }

    for (let i = 0; i < graph.length; i++) {
        if (colors[i] === 0 && !dfs(i, 1)) return false;
    }
    return true;
}

11. 拓扑排序

function topologicalSort(numCourses, prerequisites) {
    let graph = Array.from({ length: numCourses }, () => []);
    let inDegree = Array(numCourses).fill(0);
    let queue = [];
    let result = [];

    for (let [course, prereq] of prerequisites) {
        graph[prereq].push(course);
        inDegree[course]++;
    }

    for (let i = 0; i < numCourses; i++) {
        if (inDegree[i] === 0) queue.push(i);
    }

    while (queue.length) {
        let course = queue.shift();
        result.push(course);

        for (let neighbor of graph[course]) {
            inDegree[neighbor]--;
            if (inDegree[neighbor] === 0) queue.push(neighbor);
        }
    }

    return result.length === numCourses ? result : [];
}

这些实现涵盖了您列出的每个问题。代码力求简洁清晰,并使用了适当的数据结构和算法来提高效率。希望对您有所帮助!
以下是用 JavaScript 实现的解决方案:


1. 单源最短路径 (Dijkstra 算法)

function dijkstra(graph, start) {
    let distances = Array(graph.length).fill(Infinity);
    distances[start] = 0;
    let visited = new Set();

    while (visited.size < graph.length) {
        let u = -1;
        for (let i = 0; i < graph.length; i++) {
            if (!visited.has(i) && (u === -1 || distances[i] < distances[u])) {
                u = i;
            }
        }

        visited.add(u);

        for (let [v, weight] of graph[u]) {
            distances[v] = Math.min(distances[v], distances[u] + weight);
        }
    }

    return distances;
}

2. 关键连接 (桥检测)

function criticalConnections(n, connections) {
    let graph = Array.from({ length: n }, () => []);
    let discovery = Array(n).fill(-1);
    let low = Array(n).fill(-1);
    let bridges = [];
    let time = 0;

    for (let [u, v] of connections) {
        graph[u].push(v);
        graph[v].push(u);
    }

    function dfs(node, parent) {
        discovery[node] = low[node] = time++;
        for (let neighbor of graph[node]) {
            if (neighbor === parent) continue;
            if (discovery[neighbor] === -1) {
                dfs(neighbor, node);
                low[node] = Math.min(low[node], low[neighbor]);
                if (low[neighbor] > discovery[node]) {
                    bridges.push([node, neighbor]);
                }
            } else {
                low[node] = Math.min(low[node], discovery[neighbor]);
            }
        }
    }

    for (let i = 0; i < n; i++) {
        if (discovery[i] === -1) dfs(i, -1);
    }

    return bridges;
}

3. 判断负权回路 (Bellman-Ford 算法)

function hasNegativeWeightCycle(n, edges) {
    let distances = Array(n).fill(Infinity);
    distances[0] = 0;

    for (let i = 0; i < n - 1; i++) {
        for (let [u, v, weight] of edges) {
            if (distances[u] + weight < distances[v]) {
                distances[v] = distances[u] + weight;
            }
        }
    }

    for (let [u, v, weight] of edges) {
        if (distances[u] + weight < distances[v]) {
            return true;
        }
    }

    return false;
}

4. 判断图中是否存在环

function hasCycle(graph) {
    let visited = new Set();
    let stack = new Set();

    function dfs(node) {
        if (stack.has(node)) return true;
        if (visited.has(node)) return false;

        visited.add(node);
        stack.add(node);

        for (let neighbor of graph[node]) {
            if (dfs(neighbor)) return true;
        }

        stack.delete(node);
        return false;
    }

    for (let node = 0; node < graph.length; node++) {
        if (dfs(node)) return true;
    }

    return false;
}

5. 图的深度优先搜索

function dfs(graph, start) {
    let visited = new Set();
    let result = [];

    function explore(node) {
        if (visited.has(node)) return;
        visited.add(node);
        result.push(node);

        for (let neighbor of graph[node]) {
            explore(neighbor);
        }
    }

    explore(start);
    return result;
}

6. 克隆图

function cloneGraph(node) {
    if (!node) return null;

    let map = new Map();

    function clone(node) {
        if (map.has(node.val)) return map.get(node.val);

        let newNode = { val: node.val, neighbors: [] };
        map.set(node.val, newNode);

        for (let neighbor of node.neighbors) {
            newNode.neighbors.push(clone(neighbor));
        }

        return newNode;
    }

    return clone(node);
}

7. 课程表 (拓扑排序)

function canFinish(numCourses, prerequisites) {
    let graph = Array.from({ length: numCourses }, () => []);
    let inDegree = Array(numCourses).fill(0);

    for (let [course, prereq] of prerequisites) {
        graph[prereq].push(course);
        inDegree[course]++;
    }

    let queue = [];
    for (let i = 0; i < numCourses; i++) {
        if (inDegree[i] === 0) queue.push(i);
    }

    let count = 0;
    while (queue.length) {
        let course = queue.shift();
        count++;
        for (let neighbor of graph[course]) {
            inDegree[neighbor]--;
            if (inDegree[neighbor] === 0) queue.push(neighbor);
        }
    }

    return count === numCourses;
}

8. 最短路径 (Floyd-Warshall 算法)

function floydWarshall(graph) {
    let dist = graph.map(row => [...row]);

    let n = graph.length;
    for (let k = 0; k < n; k++) {
        for (let i = 0; i < n; i++) {
            for (let j = 0; j < n; j++) {
                if (dist[i][k] + dist[k][j] < dist[i][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }

    return dist;
}

9. 图的广度优先搜索

function bfs(graph, start) {
    let visited = new Set();
    let queue = [start];
    let result = [];

    while (queue.length) {
        let node = queue.shift();
        if (visited.has(node)) continue;
        visited.add(node);
        result.push(node);

        for (let neighbor of graph[node]) {
            if (!visited.has(neighbor)) {
                queue.push(neighbor);
            }
        }
    }

    return result;
}

这些实现涵盖了您所列出的所有问题。每种算法选择了高效且直观的方式,适合实际问题的解决。希望对您有所帮助!


http://www.kler.cn/a/463727.html

相关文章:

  • Chapter4.2:Normalizing activations with layer normalization
  • [Qt] Qt介绍 | 搭建SDK
  • Mac 安装 Flutter 提示 A network error occurred while checking
  • 二、CSS基础
  • 项目优化之策略模式
  • 如何利用Logo设计免费生成器创建专业级Logo
  • Harmony OS 开发-ArkUI框架速成一
  • 【深度学习】多目标融合算法—样本Loss提权
  • 2024 年发布的 Android AI 手机都有什么功能?
  • springboot529基于JavaWeb的本科生交流培养管理平台的设计与实现(论文+源码)_kaic
  • C++:Windows 多线程 简单示例
  • Ubuntu 24.04安装和使用WPS 2019
  • 2412d,d语言中写汇编
  • 机器学习 LightGBM 算法原理解析
  • QT---------GUI程序设计基础
  • Linux下Shell编程之sed命令详解及示例
  • C#语言的字符串处理
  • 上位机开发 的算法与数据结构
  • ƒ () { [native code] } 的解释
  • Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02
  • c#枚举和结构体类型详解
  • 【2024年-6月-28日-开源社区openEuler实践记录】探索 easy - software:简化软件部署与管理的开源方案
  • Ubuntu如何安装jdk并切换到不同的jdk版本
  • 【gopher的java学习笔记】mybatis的mapper是什么
  • 【C++】模板使用总结
  • MyBatis执行一条sql语句的流程(源码解析)