Leetcode每天五题-06

  1. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。
如果你可以运用递归和迭代两种方法解决这个问题,会很加分。

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;
	}
  1. 二叉树的层次遍历

给定一个二叉树,返回其按层次遍历的节点值。(即逐层地,从左到右访问所有节点)。

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;
	}
  1. 二叉树的最大深度

给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明:

叶子节点是指没有子节点的节点。

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;
	}
  1. 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 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;
	}
  1. 买卖股票的最佳时机

给定一个数组,它的第 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;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值