力扣104:二叉树的最大深度
解题思路
1、标签:DFS
2、找出终止条件:当前节点为空
3、找出返回值:节点为空时说明高度为 0,所以返回 0;节点不为空时则分别求左右子树的高度的最大值,同时加1表示当前节点的高度,返回该数值
4、某层的执行过程:在返回值部分基本已经描述清楚
5、时间复杂度:O(n)O(n)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) {
return 0;
} else {
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left, right) + 1;
}
}
}
力扣226:翻转二叉树
方法一:递归
思路与算法
这是一道很经典的二叉树问题。显然,我们从根节点开始,递归地对树进行遍历,并从叶子结点先开始翻转。如果当前遍历到的节点 \textit{root}root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 \textit{root}root 为根节点的整棵子树的翻转。
代码
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;
}
}
其实就是交换一下左右节点,然后再递归的交换左节点,右节点
根据动画图我们可以总结出递归的两个条件如下:
终止条件:当前节点为 null 时返回
交换当前节点的左右节点,再递归的交换当前节点的左节点,递归的交换当前节点的右节点
时间复杂度:每个元素都必须访问一次,所以是 O(n)O(n)
空间复杂度:最坏的情况下,需要存放 O(h)O(h) 个函数调用(h是树的高度),所以是 O(h)O(h)
代码实现如下:
class Solution {
public TreeNode invertTree(TreeNode root) {
//递归函数的终止条件,节点为空时返回
if(root==null) {
return null;
}
//下面三句是将当前节点的左右子树交换
TreeNode tmp = root.right;
root.right = root.left;
root.left = tmp;
//递归交换当前节点的 左子树
invertTree(root.left);
//递归交换当前节点的 右子树
invertTree(root.right);
//函数返回时就表示当前这个节点,以及它的左右子树
//都已经交换完了
return root;
}
}
力扣234:回文链表
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
2,使用栈解决
我们知道栈是先进后出的一种数据结构,这里还可以使用栈先把链表的节点全部存放到栈中,然后再一个个出栈,这样就相当于链表从后往前访问了,通过这种方式也能解决,看下代码
public boolean isPalindrome(ListNode head) {
ListNode temp = head;
Stack<Integer> stack = new Stack();
//把链表节点的值存放到栈中
while (temp != null) {
stack.push(temp.val);
temp = temp.next;
}
//然后再出栈
while (head != null) {
if (head.val != stack.pop()) {
return false;
}
head = head.next;
}
return true;
}
这里相当于链表从前往后全部都比较了一遍,其实我们只需要拿链表的后半部分和前半部分比较即可,没必要全部比较,所以这里可以优化一下
public boolean isPalindrome(ListNode head) {
if (head == null)
return true;
ListNode temp = head;
Stack<Integer> stack = new Stack();
//链表的长度
int len = 0;
//把链表节点的值存放到栈中
while (temp != null) {
stack.push(temp.val);
temp = temp.next;
len++;
}
//len长度除以2
len >>= 1;
//然后再出栈
while (len-- >= 0) {
if (head.val != stack.pop())
return false;
head = head.next;
}
return true;
}
力扣448:找到所有数组中消失的数字
给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。
找到所有在 [1, n] 范围之间没有出现在数组中的数字。
您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。
示例:
输入:
[4,3,2,7,8,2,3,1]
输出:
[5,6]
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
// Hash table for keeping track of the numbers in the array
// Note that we can also use a set here since we are not
// really concerned with the frequency of numbers.
HashMap<Integer, Boolean> hashTable = new HashMap<Integer, Boolean>();
// Add each of the numbers to the hash table
for (int i = 0; i < nums.length; i++) {
hashTable.put(nums[i], true);
}
// Response array that would contain the missing numbers
List<Integer> result = new LinkedList<Integer>();
// Iterate over the numbers from 1 to N and add all those
// that don't appear in the hash table.
for (int i = 1; i <= nums.length; i++) {
if (!hashTable.containsKey(i)) {
result.add(i);
}
}
return result;
}
}
时间复杂度:O(N)
空间复杂度:O(N)