110. 平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/balanced-binary-tree
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
boolean result = true;
public boolean isBalanced(TreeNode root) {
isBalanced1(root);
return result;
}
public int isBalanced1(TreeNode root) {
if(root == null){
return 0;
}
int lh = 0;
int rh = 0;
if(root.left != null){
lh = isBalanced1(root.left);
}
if(root.right != null){
rh = isBalanced1(root.right);
}
if(Math.abs(lh - rh) > 1){
result = false;
}
return Math.max(lh, rh) + 1;
}
}
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最小深度 2.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-depth-of-binary-tree
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
if(root == null){
return 0;
}
if ((root.left == null) && (root.right == null)) {
return 1;
}
int lh = 0;
int rh = 0;
int min_depth = Integer.MAX_VALUE;
if(root.left != null){
lh = minDepth(root.left);
min_depth = Math.min(lh, min_depth);
}
if(root.right != null){
rh = minDepth(root.right);
min_depth = Math.min(rh, min_depth);
}
return min_depth + 1;
}
}
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum
public boolean hasPathSum(TreeNode root, int sum) {
if(root == null){
return false;
}
sum -= root.val;
if(sum == 0 && root.left == null && root.right == null){
return true;
}
return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
}
113. 路径总和 II
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
返回:
[
[5,4,11,2],
[5,8,4,5]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum-ii
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int sum) {
helper(root, sum );
return ans;
}
public void helper(TreeNode node, int sum) {
if (node == null) {
return;
}
// 将沿途到节点加入到path中
sum -= node.val;
path.add(node.val);
// 遍历到叶节点
if (node.left == null && node.right == null) {
// 如果这是一条可行的路径,才复制path的结果到ans
if (sum == 0)
ans.add(new ArrayList<>(path));
else{
path.remove(path.size() - 1);
return ;
}
}
helper(node.left, sum );
helper(node.right, sum );
// 回溯
path.remove(path.size() - 1);
}
}
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。
输入: 5
输出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/pascals-triangle
方法:动态规划
思路
如果能够知道一行杨辉三角,我们就可以根据每对相邻的值轻松地计算出它的下一行。
算法
虽然这一算法非常简单,但用于构造杨辉三角的迭代方法可以归类为动态规划,因为我们需要基于前一行来构造每一行。
首先,我们会生成整个 triangle 列表,三角形的每一行都以子列表的形式存储。然后,我们会检查行数为 0的特殊情况,否则我们会返回 [1]。如果 numRows > 0,那么我们用 [1]作为第一行来初始化 triangle with [1],并按如下方式继续填充:
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> triangle = new ArrayList<List<Integer>>();
// First base case; if user requests zero rows, they get zero rows.
if (numRows == 0) {
return triangle;
}
// Second base case; first row is always [1].
triangle.add(new ArrayList<>());
triangle.get(0).add(1);
for (int rowNum = 1; rowNum < numRows; rowNum++) {
List<Integer> row = new ArrayList<>();
List<Integer> prevRow = triangle.get(rowNum-1);
// The first row element is always 1.
row.add(1);
// Each triangle element (other than the first and last of each row)
// is equal to the sum of the elements above-and-to-the-left and
// above-and-to-the-right.
for (int j = 1; j < rowNum; j++) {
row.add(prevRow.get(j-1) + prevRow.get(j));
}
// The last row element is always 1.
row.add(1);
triangle.add(row);
}
return triangle;
}
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutations
class Solution {
List<List<Integer>> lists= new ArrayList<>();
List<Integer> list = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
permute1(nums, 0, nums.length -1);
return lists;
}
public void permute1(int[] nums,int start ,int end) {
if(start == end ){
for (int i = 0; i < nums.length; i++) {
list.add(nums[i]);
}
lists.add(new ArrayList<>(list));
list.clear();
}
for (int i = start; i <= end; i++) {
swap(nums, i, start);
permute1(nums, start + 1 , end);
swap(nums, start, i);
}
}
public void swap(int[] nums,int i , int k){
int temp = nums[i];
nums[i] = nums[k];
nums[k] = temp;
}
}
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<Integer> qun = new PriorityQueue<>();
for (int i = 0; i < lists.length; i++) {
while(lists[i] != null){
qun.add(lists[i].val);
lists[i] = lists[i].next;
}
}
ListNode head = new ListNode(-1);
ListNode next = head;
while(!qun.isEmpty()){
next.next = new ListNode(qun.remove());
next = next.next;
}
return head.next;
}
}
给定一个数组,它的第 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。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
第一种解法
public int maxProfit(int[] prices) {
if(prices== null || prices.length == 0){
return 0;
}
int[] dp = new int[prices.length];
for (int i = 0; i < prices.length; i++) {
int max = Integer.MIN_VALUE;
for (int j = i+1; j < prices.length; j++) {
if(prices[j] - prices[i] > max){
max = prices[j] - prices[i];
}
}
if(max > 0 ){
dp[i] = max;
}else{
dp[i] = 0;
}
}
int result = dp[0];
for (int i = 1; i < dp.length; i++) {
if(dp[i] > result){
result = dp[i];
}
}
return result;
}
第二种解法
public int maxProfit1(int prices[]) {
int maxprofit = 0;
for (int i = 0; i < prices.length - 1; i++) {
for (int j = i + 1; j < prices.length; j++) {
int profit = prices[j] - prices[i];
if (profit > maxprofit)
maxprofit = profit;
}
}
return maxprofit;
}
第三种
public int maxProfit2(int prices[]) {
int minprice = Integer.MAX_VALUE;
int maxprofit = 0;
for (int i = 0; i < prices.length; i++) {
if (prices[i] < minprice)
minprice = prices[i];
else if (prices[i] - minprice > maxprofit)
maxprofit = prices[i] - minprice;
}
return maxprofit;
}
第三种的思路
假设给定的数组为:
[7, 1, 5, 3, 6, 4]
如果我们在图表上绘制给定数组中的数字,我们将会得到:
使我们感兴趣的点是上图中的峰和谷。我们需要找到最小的谷之后的最大的峰。
我们可以维持两个变量——minprice 和 maxprofit,它们分别对应迄今为止所得到的最小的谷值和最大的利润(卖出价格与最低价格之间的最大差值)。