【LeetCode热题100】打卡第40天:翻转二叉树&回文链表

文章目录

  • 【LeetCode热题100】打卡第40天:翻转二叉树&回文链表
    • ⛅前言
  • 翻转二叉树
    • 题目
    • 题解
  • 回文链表
    • 题目
    • 题解

【LeetCode热题100】打卡第40天:翻转二叉树&回文链表

⛅前言

大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!

精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。

博客主页:知识汲取者的博客

LeetCode热题100专栏:LeetCode热题100

Gitee地址:知识汲取者 (aghp) - Gitee.com

题目来源:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激

翻转二叉树

题目

原题链接:226.翻转二叉树

【LeetCode热题100】打卡第40天:翻转二叉树&回文链表_第1张图片

题解

  • 解法一:递归

    刷LeetCode热题100也有一个月了,现在有那么一丢丢的感觉了,遇到树相关的问题,绝大多数递归就对了。

    这题同样使用递归,递归遍历左右子树一下就决解了,不愧是简单题,思路也很简单:先递归到最后一层,然后自底向上交换当前节点左右节点,这样就能够实现翻转二叉树了

    public class Solution {
        public TreeNode invertTree(TreeNode root) {
            if (root == null) {
                return null;
            }
            TreeNode left = invertTree(root.left);
            TreeNode right = invertTree(root.right);
            root.left = right;
            root.right = left;
            return root;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n),递归遍历树,需要遍历到每一个节点,所以时间复杂度自然是 O ( n ) O(n) O(n)
    • 空间复杂度: O ( l o g h ) O(logh) O(logh),递归遍历树,空间复杂度取决去树的高度

    其中 n n n 为树中节点的个数, h h h是树的高度

  • 解法二:迭代

    迭代本质和递归是一样的,只是将隐士的栈变成了显示的栈,和上面解法是完全等价的。

    不是很懂的可以区看这篇文章:【LeetCode热题100】打卡第27天:二叉树的前序、中序、后序遍历,这篇文章对迭代遍历树有较为详细的讲解

    public class Solution {
        public TreeNode invertTree(TreeNode root) {
            Deque<TreeNode> stack = new LinkedList<>();
            TreeNode cur = root;
            while (!stack.isEmpty() || cur != null) {
                // 遍历当前节点的左子树
                while (cur != null) {
                    stack.push(cur);
                    // 将指针指向左子节点
                    cur = cur.left;
                }
                TreeNode node = stack.pop();
                // 交换左右子节点
                TreeNode left = node.left;
                TreeNode right = node.right;
                node.left = right;
                node.right = left;
                // 将指针指向右子节点
                cur = right;
            }
            return root;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n),递归遍历树,需要遍历到每一个节点,所以时间复杂度自然是 O ( n ) O(n) O(n)
    • 空间复杂度: O ( l o g h ) O(logh) O(logh),递归遍历树,空间复杂度取决去树的高度

    其中 n n n 为树中节点的个数, h h h是树的高度

  • 解法三:利用遍历交换左右子节点

    在遍历的同时,可以交换左右节点,至于二叉树的遍历方式就有很多种了,常见的比如:中序后序前序层序,遍历方式又可以分为:递归、迭代,这么算起来,解法三就有 8 种不同的实现方式了,这里我就只列举一种,其它方式,大家可以自己参考这我上一个解法中提到的那篇文章进行实现,这里我就使用层序遍历实现一下,关于层序遍历详细可以参考我的这篇文章:【LeetCode热题100】打卡第29天:二叉树的层序遍历,层序遍历的核心实现思路就是 BFS

    PS:其实解法一和解法二本质上就是采用中序遍历的思想:先左后中再右

    public class Solution {
        public TreeNode invertTree(TreeNode root) {
            if (root == null) {
                // 防止后面出现NPE
                return null;
            }
            Deque<TreeNode> queue = new LinkedList<>();
            queue.offer(root);
            while (!queue.isEmpty()) {
                TreeNode node = queue.poll();
                TreeNode left = node.left;
                TreeNode right = node.right;
                node.left = right;
                node.right = left;
                if (left != null) {
                    queue.offer(left);
                }
                if (right != null) {
                    queue.offer(right);
                }
            }
            return root;
        }
    }
    

回文链表

题目

原题链接:234.回文链表

【LeetCode热题100】打卡第40天:翻转二叉树&回文链表_第2张图片

题解

  • 解法一:暴力

    最直接的方法,遍历所有的节点,利用StringBuilder进行拼接,然后判断反转后的内容是否一致,如果一致则说明当前链表是一个回文串,否则不是,这里有一个比较坑的点,就是StringBuilder没有重写Object的toString方法,所以如果调用equals方法,比较的地址,所以这里我们需要将StringBuilder转成String(String重写了Object的toString方法),然后再调用equals方法进行比较

    public class Solution {
        public boolean isPalindrome(ListNode head) {
            StringBuilder sb = new StringBuilder();
            while (head != null) {
                sb.append(head.val);
                head = head.next;
            }
            String str1 = new StringBuilder(sb).reverse().toString();
            String str2 = sb.toString();
            return str1.equals(str2);
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( n ) O(n) O(n)

    其中 n n n 为链表中元素的个数

  • 解法二:快慢指针

    在写链表相关题目时,已经好几次遇到快慢指针了,从最开始的“我靠,还有这种方式“、到后来的“额原来还可以这样写”,再到现在的”不就是快慢指针吗,这不有手就行“(我还没到这一种心态,我还在第二种心态o((>ω< ))o)

    算法实现的主要核心思路:快指针走到末尾,慢指针刚好到中间。其中慢指针将前半部分反转。然后比较

    关于反转链表的部分我们可以参考这一题:【LeetCode热题100】打卡第37天:反转链表

    关于快慢指针的部分我们可以参考这一题:【LeetCode热题100】打卡第34天:排序链表

    /**
     * @author ghp
     * @title
     */
    public class Solution {
        public boolean isPalindrome(ListNode head) {
            if (head.next == null) {
                // 链表只有一个节点,直接返回,防止后面出现NPE
                return true;
            }
            ListNode fast = head, slow = head, pre = null;
            // 定位中间节点,同时反转链表的前半段
            while (fast != null && fast.next != null) {
                // fast多走一步
                fast = fast.next.next;
                // 反转前半段链表
                ListNode next = slow.next;
                slow.next = pre;
                pre = slow;
                slow = next;
            }
            if (fast != null) {
                // 当前链表具有偶数个节点,还需要将slow往后移动一位
                slow = slow.next;
            }
            // 逐个比较 反转后的前半段链表 和 未反转的后半段链表 的节点的val是否相等
            while (pre != null && slow != null) {
                if (pre.val != slow.val) {
                    // 有一个节点的val不相等,说明当前链表不是回文链表
                    return false;
                }
                pre = pre.next;
                slow = slow.next;
            }
            // 前后两截链表的val都相等,则说明当前链表是回文链表
            return true;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( 1 ) O(1) O(1)

    其中 n n n 为链表中元素的个数

你可能感兴趣的:(#,LeetCode热题100,Programming,practice,leetcode,链表,算法)