链表和树的leetcode题

news/2025/2/23 9:38:32

基础新手

链表

注意事项

注意保存上下文环境。注意gc,不要有垃圾变量。换头结点注意考虑头

对于链表不要在乎是O(n)还是O(2n)

长短链表互换

习题

K个节点的组内逆序调整 ?

leetcode:K 个一组翻转链表

找n函数

逆转函数

第一组是否找齐

之后每组处理:start先指向下一组头,遍历完再指向尾

不在于算法,而在于coding能力

链表相加

注意长短链表互换,链表1结点+链表2结点+进位,注意最后进位需要补结点

阶段1:两个相加+进位 while(shortNode != null)

阶段2:单个链表+进位 while(longNode != null)

阶段3:链表结束,仍有进位,补结点 if(carry != 0)

上面三个阶段分别是3个循环

有序链表合并

注意换头,有一个为空就出循环

合并K个升序链表

leetcode:合并K个升序链表

利用小根堆,注意返回空

m条链表,总结点n个。时间复制度 O(log(m)*n)

class Solution {
    class PackageNode {
        ListNode node;
        Integer index;
        public PackageNode(ListNode node, Integer index) {
            this.node = node;
            this.index = index;
        }
    }
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists.length == 0) {
            return null;
        }
        ListNode head = null;
        ListNode p = head;
        PriorityQueue<PackageNode> priorityQueue = new PriorityQueue<>(lists.length, Comparator.comparingInt(a -> a.node.val));
        for (int i = 0; i < lists.length; i++) {
            if (lists[i] != null) {
                priorityQueue.add(new PackageNode(lists[i], i));
                lists[i] = lists[i].next;
            }
        }
        while (priorityQueue.size() > 0) {
            PackageNode packageNode = priorityQueue.poll();
            Integer index = packageNode.index;
            if (lists[index] != null) {
                priorityQueue.add(new PackageNode(lists[index], index));
                lists[index] = lists[index].next;
            }
            if (head == null) {
                head = packageNode.node;
                p = head;
            } else {
                p.next = packageNode.node;
                p = p.next;
            }
        }
        return head;
    }
}

注意事项

对于全都遍历的,使用递归很方便

习题

判断两棵是否相同

leetcode:相同的

注意异或^的使用,只有一个成立时为真

对于全都遍历的,使用递归很方便!!!

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        ArrayList<TreeNode> list1 = new ArrayList<>();
        ArrayList<TreeNode> list2 = new ArrayList<>();
        list1.add(p);
        list2.add(q);
        while (!list1.isEmpty() && !list2.isEmpty()) {
            p = list1.remove(0);
            q = list2.remove(0);
            if (p == null && q == null) {
                continue;
            } else if (p != null ^ q != null) {
                return false;
            }
            if (p.val != q.val) {
                return false;
            }
            if (p.left != null && q.left != null) {
                list1.add(p.left);
                list2.add(q.left);
            } else if (p.left == null ^ q.left == null) {
                return false;
            }
            if (p.right != null && q.right != null) {
                list1.add(p.right);
                list2.add(q.right);
            } else if (p.right == null ^ q.right == null) {
                return false;
            }
        }
        return list1.isEmpty() && list2.isEmpty();
    }
}

判断是否是镜面

leetcode:对称二叉

虽然是简单,但是也做了不少时间

传两个头结点(left,right)!!!我又用了层序遍历

判断left.val == right.val && fun(left.left, right.right) && fun(left.right, right.left)

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return isSymmetric(root, root);
    }
    public boolean isSymmetric(TreeNode p, TreeNode q) {
        if (p == null ^ q == null) {
            return false;
        }
        if (p == null && q == null) {
            return true;
        }
        return p.val == q.val && isSymmetric(p.left, q.right) && isSymmetric(p.right, q.left);
    }
    public boolean isSymmetricLevel(TreeNode root) {
        if (root == null) {
            return true;
        }
        ArrayList<TreeNode> treeList = new ArrayList<>();
        treeList.add(root);
        while (!treeList.isEmpty()) {
            if (treeList.size() > 1 && (treeList.size() & 1) != 0) {
                return false;
            }
            int len = treeList.size();
            for (int i = 0; i < len >> 1; i++) {
                int leftIndex = len - i - 1;
                if (treeList.get(i) == null ^ treeList.get(leftIndex) == null) {
                    return false;
                }
                if (treeList.get(i) == null && treeList.get(leftIndex) == null) {
                    continue;
                }
                if (treeList.get(i).val != treeList.get(leftIndex).val) {
                    return false;
                }
                treeList.add(treeList.get(i).left);
                treeList.add(treeList.get(i).right);
            }
            for (int i = len >> 1; i < len; i++) {
                if (treeList.get(i) == null) {
                    continue;
                }
                treeList.add(treeList.get(i).left);
                treeList.add(treeList.get(i).right);
            }
            for (int i = 0; i < len; i++) {
                treeList.remove(0);
            }
        }
        return true;
    }
}

返回的最大深度

leetcode:二叉的最大深度

用递归思想代码十分简单。差点又想用层序

class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
    }
}

先序遍历和中序遍历建

leetcode:从前序与中序遍历序列构造二叉

没啥说的,常见题

    class Solution {
        HashMap<Integer, Integer> numSite = new HashMap<>();
        public TreeNode buildTree(int[] preorder, int[] inorder) {
            if (preorder.length <= 0) {
                return null;
            }
            for (int i = 0; i < inorder.length; i++) {
                numSite.put(inorder[i], i);
            }
            return buildTree(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
        }
        public TreeNode buildTree(int[] preorder, int preLow, int preHigh, int[] inorder, int inLow, int inHigh) {
            if (preLow > preHigh) {
                return null;
            }
            TreeNode head = new TreeNode(preorder[preLow]);
            if (preLow < preHigh) {
                int index = numSite.get(head.val);
                head.left = buildTree(preorder, preLow + 1, preLow + (index - inLow), inorder, inLow, index - 1);
                head.right = buildTree(preorder, preLow + (index - inLow) + 1, preHigh, inorder, index + 1, inHigh);
            }
            return head;
        }
    }


http://www.niftyadmin.cn/n/249508.html

相关文章

C语言模拟银行排队叫号(链队)

一.队列 队列是一种具有先进先出&#xff08;FIFO&#xff09;特性的线性数据结构&#xff0c;它只允许在队列的两端进行插入和删除操作。队列的一端称为队尾&#xff08;rear&#xff09;&#xff0c;另一端称为队头&#xff08;front&#xff09;。新元素总是插入在队列的队…

WinScp密钥登录

使用密码登录非常的方便&#xff0c;但是有的客户的云服务器上是限定只能通过密钥登录。我一般使用命令行的scp命令就可以正常上传&#xff0c;但是对于我一些同事来说&#xff0c;就很不方便。 生成密钥 这个不难&#xff0c;可以参考我之前的文章。 《Mac使用ssh连接远程服…

【华为OD机试真题 C++】1071 - N进制减法 | 机试题+算法思路+考点+代码解析

文章目录 一、题目&#x1f538;题目描述&#x1f538;输入输出&#x1f538;样例1&#x1f538;样例2 二、代码参考 作者&#xff1a;KJ.JK &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308;…

Python批量梯度下降法的举例

梯度下降法 梯度下降法是一种常用的优化算法&#xff0c;用于求解目标函数的最小值。其基本思想是&#xff0c;通过不断地朝着函数梯度下降的方向更新参数&#xff0c;直到找到函数的最小值。 具体来说&#xff0c;假设我们有一个可导的目标函数 f ( x ) f(x) f(x)&#xff…

妙用Java 8中的 Function接口,消灭if...else

在开发过程中经常会使用if...else...进行判断抛出异常、分支处理等操作。这些if...else...充斥在代码中严重影响了代码代码的美观&#xff0c;这时我们可以利用Java 8的Function接口来消灭if...else...。 if (...){throw new RuntimeException("出现异常了")&#x…

编码拓展:链接库

一.认识链接库 1.1库 计算机中&#xff0c;有些文件专门用于存储可以重复使用的代码块&#xff0c;例如功能实用的函数或者类&#xff0c;我们通常将它们称为库文件&#xff0c;简称“库”&#xff08;Library&#xff09;。 以 C 语言为例&#xff0c;如下为大家展示的就是…

页面注册案例

效果图&#xff1a; 分析业务模块&#xff1a; 发送验证码模块各个表单验证模块勾选已经阅读同意模块下一步验证全部模块&#xff1a;只要上面有一个input验证不通过就不同意提交 业务 1 &#xff1a;发送验证码 用户点击之后&#xff0c;显示05秒后重新获取时间到了&…

Spring6从入门到精通 第一章 带你玩转Spring

这里写目录标题 一 Spring框架产生的原因二 Spring6配置的关键环节 一 Spring框架产生的原因 传统的JavaWeb存在着耦合度较高的问题&#xff0c;而且实现完整的的MVC三层架构&#xff0c;开发成本过大&#xff0c;因此出现了Spring这个轻量级的开发框架&#xff0c;相当于建筑里…