5、栈、队列、优先队列

内容来自刘宇波老师玩转算法面试

1、栈的基础应用

20 - 有效的括号

image

public static boolean isValid(String s) {
    Stack<Character> stack = new Stack<>();

    char[] chars = s.toCharArray();
    for (char c : chars) {
        if (c == '(' || c == '{' || c == '[') stack.push(c);
        else {
            if (stack.isEmpty()) return false;
            char top = stack.pop();
            if (c == ')' && top != '(') return false;
            if (c == '}' && top != '{') return false;
            if (c == ']' && top != '[') return false;
        }
    }

    return stack.isEmpty();
}

更多问题
150 - 逆波兰表达式求值
71 - 简化路径

2、栈和递归的密切关系

public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode() {
    }

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

更多问题
341 - 扁平化嵌套列表迭代器

2.1、二叉树的前序遍历

144 - 二叉树的前序遍历

递归实现

image

public static List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    preOrder(root, list);
    return list;
}

private static void preOrder(TreeNode root, List<Integer> list) {
    if (root == null) return;

    list.add(root.val);
    preOrder(root.left, list);
    preOrder(root.right, list);
}

用栈实现

image

public class Solution {

    private static class Command {
        public String s; // go, print
        public TreeNode node;

        public Command(String command, TreeNode node) {
            this.s = command;
            this.node = node;
        }
    }

    public static List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if (root == null) return list;

        Stack<Command> stack = new Stack<>();
        stack.push(new Command("go", root));

        while (!stack.isEmpty()) {
            Command command = stack.pop();
            String s = command.s;
            TreeNode node = command.node;

            if (s.equals("print")) list.add(node.val);
            else {
                if (node.right != null) stack.push(new Command("go", node.right));
                if (node.left != null) stack.push(new Command("go", node.left));
                stack.push(new Command("print", node));
            }
        }

        return list;
    }
}
public static List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();
    if (root != null) stack.push(root);

    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        list.add(node.val);
        if (node.right != null) stack.push(node.right);
        if (node.left != null) stack.push(node.left);
    }
    return list;
}

2.2、二叉树的中序遍历

94 - 二叉树的中序遍历

递归实现

public static List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    inorder(root, list);
    return list;
}

private static void inorder(TreeNode node, List<Integer> list) {
    if (node == null) return;

    if (node.left != null) inorder(node.left, list);
    list.add(node.val);
    if (node.right != null) inorder(node.right, list);
}

用栈实现

public class Solution {

    private static class Command {
        public String s; // go, print
        public TreeNode node;

        public Command(String s, TreeNode node) {
            this.s = s;
            this.node = node;
        }
    }

    public static List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if (root == null) return list;

        Stack<Command> stack = new Stack<>();
        stack.push(new Command("go", root));

        while (!stack.isEmpty()) {
            Command command = stack.pop();
            String s = command.s;
            TreeNode node = command.node;

            if (s.equals("print")) list.add(node.val);
            else {
                if (node.right != null) stack.push(new Command("go", node.right));
                stack.push(new Command("print", node));
                if (node.left != null) stack.push(new Command("go", node.left));
            }
        }

        return list;
    }
}

2.3、二叉树的后序遍历

145 - 二叉树的后序遍历

递归实现

public static List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    postOrder(root, list);
    return list;
}

private static void postOrder(TreeNode node, List<Integer> list) {
    if (node == null) return;

    if (node.left != null) postOrder(node.left, list);
    if (node.right != null) postOrder(node.right, list);
    list.add(node.val);
}

用栈实现

public class Solution {

    private static class Command {
        public String s; // go, print
        public TreeNode node;

        public Command(String s, TreeNode node) {
            this.s = s;
            this.node = node;
        }
    }

    public static List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if (root == null) return list;

        Stack<Command> stack = new Stack<>();
        stack.push(new Command("go", root));

        while (!stack.isEmpty()) {
            Command command = stack.pop();
            String s = command.s;
            TreeNode node = command.node;

            if (s.equals("print")) list.add(node.val);
            else {
                stack.push(new Command("print", node));
                if (node.right != null) stack.push(new Command("go", node.right));
                if (node.left != null) stack.push(new Command("go", node.left));
            }
        }

        return list;
    }
}

3、队列的典型应用

image

102 - 二叉树的层序遍历

private static class Pair<A, B> {
    public final A first;
    public final B second;

    public Pair(A key, B value) {
        this.first = key;
        this.second = value;
    }
}

public static List<List<Integer>> levelOrder1(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    if (root == null) return res;

    Queue<Pair<TreeNode, Integer>> queue = new LinkedList<>();
    queue.add(new Pair<>(root, 0));

    while (!queue.isEmpty()) {
        TreeNode node = queue.peek().first;
        int level = queue.peek().second;
        queue.remove();

        if (level == res.size()) res.add(new ArrayList<>());
        res.get(level).add(node.val);

        if (node.left != null) queue.add(new Pair<>(node.left, level + 1));
        if (node.right != null) queue.add(new Pair<>(node.right, level + 1));
    }

    return res;
}

public static List<List<Integer>> levelOrder2(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    if (root == null) return res;

    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);

    while (!queue.isEmpty()) {
        List<Integer> list = new ArrayList<>();
        int size = queue.size();

        for (int i = 0; i < size; i++) {
            TreeNode node = queue.remove();
            list.add(node.val);
            if (node.left != null) queue.add(node.left);
            if (node.right != null) queue.add(node.right);
        }

        res.add(list);
    }

    return res;
}

更多问题
107 - 二叉树的层序遍历 II
103 - 二叉树的锯齿形层序遍历
199 - 二叉树的右视图

4、BFS 和图的最短路径

279 - 完全平方数


5、优先队列相关的算法问题

347 - 前 K 个高频元素

private static class Pair implements Comparable<Pair> {
    public int value;
    public int freq;

    public Pair(int value, int freq) {
        this.value = value;
        this.freq = freq;
    }

    @Override
    public int compareTo(Pair o) {
        return this.freq - o.freq;
    }
}

public static int[] topKFrequent(int[] nums, int k) {
    // 统计每个元素出现的频率 value : freq
    Map<Integer, Integer> map = new HashMap<>();
    for (int num : nums) map.put(num, map.getOrDefault(num, 0) + 1);

    // 扫描 map, 维护当前出现频率最高的 k 个元素
    PriorityQueue<Pair> pq = new PriorityQueue<>(); // 最小堆

    Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
    for (Map.Entry<Integer, Integer> entry : entries) {
        Pair pair = new Pair(entry.getKey(), entry.getValue());

        if (pq.size() < k) pq.add(pair);
        else if (pair.freq > pq.peek().freq) {
            pq.remove();
            pq.add(pair);
        }
    }

    int[] res = new int[k];
    for (int i = 0; i < res.length; i++) res[i] = pq.remove().value;
    return res;
}

更多问题
23 - 合并 K 个升序链表

posted @ 2023-05-12 18:30  lidongdongdong~  阅读(6)  评论(0编辑  收藏  举报