返回

巧用技巧,轻松攻克 LeetCode 数组转链表和树形题

前端

LeetCode 是备受推崇的算法学习平台,它为开发者提供了大量挑战性的题目来磨炼自己的编程技能。其中,数组转链表和树形题是两大常见类型,掌握相关技巧至关重要。本文将介绍一些实用方法,让您在面对此类问题时游刃有余。

数组转链表

方法 1:使用哑结点

这是一个简单易行的方案,只需创建一个虚拟的哑结点,作为链表的头结点。然后逐个遍历数组元素,将它们插入哑结点之后,最后返回哑结点的 next 指针指向的实际头结点即可。

方法 2:递归

递归是一种简洁且高效的解决方案。基本思路是将数组拆分为头部和尾部,然后将头部节点与递归构造的尾部链表连接起来。

树形题

方法 1:利用官方提供的类

LeetCode 提供了 ListNode 和 TreeNode 类,分别用于表示链表和树节点。利用这些类可以极大简化代码编写,但需要付费会员才能使用测试用例。

方法 2:自定义数据结构

如果您没有会员资格,也可以自行定义链表和树节点的数据结构。这里提供两种简单的实现:

自定义链表节点:

class ListNode {
    int val;
    ListNode next;
    public ListNode(int val) {
        this.val = val;
    }
}

自定义树节点:

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

其他技巧

  • 合理使用双指针: 双指针技巧在数组和链表问题中尤为有用,可以有效地简化代码。
  • 善于利用栈: 栈数据结构可以帮助解决诸如树的深度优先遍历和二叉树的后序遍历等问题。
  • 灵活运用递归: 递归是解决树形问题和动态规划问题的有力工具。

示例代码

数组转链表(方法 1)

public ListNode arrayToList(int[] nums) {
    ListNode dummy = new ListNode(0);
    ListNode curr = dummy;
    for (int num : nums) {
        curr.next = new ListNode(num);
        curr = curr.next;
    }
    return dummy.next;
}

二叉树构建(方法 2)

public TreeNode buildTree(int[] preorder, int[] inorder) {
    if (preorder.length == 0) {
        return null;
    }
    int rootVal = preorder[0];
    TreeNode root = new TreeNode(rootVal);
    int rootIndex = -1;
    for (int i = 0; i < inorder.length; i++) {
        if (inorder[i] == rootVal) {
            rootIndex = i;
            break;
        }
    }
    root.left = buildTree(Arrays.copyOfRange(preorder, 1, rootIndex + 1), Arrays.copyOfRange(inorder, 0, rootIndex));
    root.right = buildTree(Arrays.copyOfRange(preorder, rootIndex + 1, preorder.length), Arrays.copyOfRange(inorder, rootIndex + 1, inorder.length));
    return root;
}