给定一个二叉树,检查它是否是镜像对称的。
如果你可以运用递归和迭代两种方法解决这个问题,会很加分。
class Solution {
public static boolean isSymmetric(TreeNode root) {
if (root == null)
return true;
return isSymmetric(root.left, root.right);
}
public static boolean isSymmetric(TreeNode left, TreeNode right) {
if (left == right) { // 都为null
return true;
}
if ((left == null || right == null)) { // 有一个不为null
return false;
}
// 一般情况
if (left.val == right.val && isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left)) {
return true;
}
return false;
}
}
迭代写法
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
if (root.left == null && root.right == null) {
return true;
}
if (root.left == null && root.right != null || root.right == null && root.left != null) {
return false;
}
TreeNode leftroot = root.left;
TreeNode rightroot = root.right;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(leftroot);
queue.add(rightroot);
while (!queue.isEmpty()) {
TreeNode le = queue.poll();
TreeNode ri = queue.poll();
if (le == null && ri == null) {
continue;
}
if (le == null || ri == null || le.val != ri.val) {
return false;
}
queue.add(le.left);
queue.add(ri.right);
queue.add(le.right);
queue.add(ri.left);
}
return true;
}
给定一个二叉树,返回其按层次遍历的节点值。(即逐层地,从左到右访问所有节点)。
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
if (root == null) {
return ans;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (queue.size() > 0) {
int size = queue.size();
List<Integer> list = new ArrayList<>();
//将上层所有结点出队以后,下层的结点数也就确定了
while (size-- > 0) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
list.add(node.val);
}
ans.add(list);
}
return ans;
}
}
一重循环版本
public static List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
if (root == null) {
return ans;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int preSize = 1;
int curSize = 0;
List<Integer> list = new ArrayList<>();
while (queue.size() > 0) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
curSize++;
}
if (node.right != null) {
queue.add(node.right);
curSize++;
}
// 必须在后面
preSize--;
if (preSize >= 0) {
list.add(node.val);
}
if (preSize == 0) {
ans.add(list);
list = new ArrayList<>();
preSize = curSize;
curSize = 0;
}
}
return ans;
}
给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明:
叶子节点是指没有子节点的节点。
class Solution {
public int maxDepth(TreeNode root) {
return root == null ?0:Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
}
}
两种非递归实现
思路都差不多,访问完每一层的结点数之后层数加一
public static int maxDepth1(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
int preCount = 1;
int curCount = 0;
int level = 0;
while (!q.isEmpty()) {
TreeNode temp = q.poll();
preCount--;
if (temp.left != null) {
q.offer(temp.left);
curCount++;
}
if (temp.right != null) {
q.offer(temp.right);
curCount++;
}
if (preCount == 0) {
preCount = curCount;
curCount = 0;
level++;
}
}
return level;
}
public int maxDepth2(TreeNode root) {
if (root == null) {
return 0;
}
int level = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
level++;
int n = queue.size();
while (n > 0) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
n--;
}
}
return level;
}
根据一棵树的前序遍历与中序遍历构造二叉树。注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
public static TreeNode buinLeftdTree(int[] preorder, int[] inorder) {
if (preorder == null || preorder == null) {
return null;
}
// 用map记录中序序列的位置
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return buinLeftdTree(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
public static TreeNode buinLeftdTree(int[] preorder, int preLeft, int preRight, int[] inorder, int inLeft,
int inRight) {
// return
if (preLeft > preRight || inLeft > inRight) {
return null;
}
TreeNode head = new TreeNode(preorder[preLeft]);
int s = map.get(preorder[preLeft]);
// -il是为了去掉已经构建的部分
head.left = buinLeftdTree(preorder, preLeft + 1, preLeft + s - inLeft, inorder, inLeft, s - 1);
head.right = buinLeftdTree(preorder, preLeft + s + 1 - inLeft, preRight, inorder, s + 1, inRight);
return head;
}
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是7-1=6,因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
将原问题转换成最大子数组和问题
class Solution {
public int maxProfit(int[] prices) {
if(prices == null || prices.length == 0){
return 0;
}
int dp[] = new int[prices.length];
int ans = 0;
int tmpSum = 0;
for(int i=1;i<dp.length;i++){
dp[i] = prices[i] - prices[i-1];
tmpSum = tmpSum < 0 ? dp[i] : tmpSum + dp[i];
ans = Math.max(ans,tmpSum);
}
return ans;
}
}
省略dp数组的解法
public static int maxProfit2(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
int ans = 0;
int tmpSum = 0;
for (int i = 1; i < prices.length; i++) {
tmpSum = tmpSum < 0 ? prices[i] - prices[i - 1] : tmpSum + prices[i] - prices[i - 1];
ans = Math.max(ans, tmpSum);
}
return ans;
}