文章目录
- 【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也有一个月了,现在有那么一丢丢的感觉了🤣,遇到树相关的问题,绝大多数递归就对了。
这题同样使用递归,递归遍历左右子树一下就决解了,不愧是简单题,思路也很简单:先递归到最后一层,然后自底向上交换当前节点左右节点,这样就能够实现翻转二叉树了
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.回文链表
🔑题解
-
解法一:暴力
最直接的方法,遍历所有的节点,利用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 为链表中元素的个数