今天事情比较多,主要来复习一下树型数据结构及贪心算法。
二叉树最小深度
给定一个二叉树,找出其最小深度。
深度优先
思路
(1)如果是叶子节点的话,我们可以将其深度设置为1;
(2)如果不是叶子节点,对比其左右子节点的深度以及之前遍历时保存的最小的深度,选其中最小,最终输出min+1即为本题的解。
package test;
public class TreeDeep {
static class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int val, TreeNode left, TreeNode right){
this.val = val;
this.left = left;
this.right = right;
}
}
public static void main(String[] args) {
TreeNode node7 = new TreeNode(7,null,null);
TreeNode node6 = new TreeNode(6,node7,null);
TreeNode node5 = new TreeNode(5,null,null);
TreeNode node4 = new TreeNode(4,null,null);
TreeNode node3 = new TreeNode(3,node6,null);
TreeNode node2 = new TreeNode(2,node4,node5);
TreeNode node1 = new TreeNode(1,node2,node3);
System.out.println(minDepth(node1));
}
//深度优先
public static int minDepth(TreeNode root) {
if(root == null) {
return 0;
}
//叶子节点
if(root.left == null && root.right == null) {
return 1;
}
int min = Integer.MAX_VALUE;
if(root.left != null) {
min = Math.min(minDepth(root.left), min);
}
if(root.right != null) {
min = Math.min(minDepth(root.right),min);
}
return min + 1;
}
}
广度优先
思路
(1)先将root的深度值设置为1。之后使用队列,将root放入队列中;
(2)如果左右节点为空,则说明找到最小深度所处的节点了,直接返回deep值;
(3)如果左节点不为空,则首先将左节点的深度在父节点深度的基础上加1,再将其放入队列中;
(4)如果右节点不空,同理。
package test;
import java.util.LinkedList;
import java.util.Queue;
public class TreeDeep {
static class TreeNode{
int val;
TreeNode left;
TreeNode right;
int deep;
TreeNode(int val, TreeNode left, TreeNode right, int deep){
this.val = val;
this.left = left;
this.right = right;
this.deep = deep;
}
}
public static void main(String[] args) {
TreeNode node7 = new TreeNode(7,null,null,0);
TreeNode node6 = new TreeNode(6,node7,null,0);
TreeNode node5 = new TreeNode(5,null,null,0);
TreeNode node4 = new TreeNode(4,null,null,0);
TreeNode node3 = new TreeNode(3,node6,null,0);
TreeNode node2 = new TreeNode(2,node4,node5,0);
TreeNode node1 = new TreeNode(1,node2,node3,0);
//System.out.println(minDepth(node1));
System.out.println(minDepth2(node1));
}
//广度优先
public static int minDepth2(TreeNode root) {
if(root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
root.deep = 1;
queue.offer(root);
while(!queue.isEmpty()) {
TreeNode node = queue.poll();
if(node.left == null && node.right == null) {
return node.deep;
}
if(node.left != null) {
node.left.deep = node.deep + 1;
queue.offer(node.left);
}
if(node.right != null) {
node.right.deep = node.deep + 1;
queue.offer(node.right);
}
}
return 0;
}
}
总结
深度优先是将叶子节点的深度设置为1,广度优先是将根节点深度设置为1。
在时间复杂度上,深度优先和广度优先都是O(n);
在空间复杂度上,深度优先取决于树的深度,为O(logn),广度优先的空间复杂度为O(n)。
最长连续递增序列
思路
贪心算法。
设定两个指针i和j。首先i指向0的位置,j指向1的位置。设定count初始值为1,max初始值为0。
(1)如果nums[i]小于等于nums[j],则说明可以继续进行,i++,j++,count++,同时取count和max中的最大值;
(2)相反,将j指向的值给i,然后j++。
package test;
public class MaxSeq {
public static void main(String[] args) {
int[] nums = new int[] {1,2,3,2,3,4,3,4,5,6,7};
System.out.println(fingLength(nums));
}
//贪心算法
public static int fingLength(int[] nums) {
int start = 0;
int max = 0;
for(int i = 1; i< nums.length; i++) {
if(nums[i]<=nums[i-1]) {
start = i;
}
max = Math.max(max, i - start + 1);
}
return max;
}
//test
public static int fingLength1(int[] nums) {
int i = 0, j = 1;
int count = 1, max = 0;
while(j < nums.length) {
if(nums[i] <= nums[j]) {
i++;j++;
count++;
max = Math.max(count, max);
}else {
i = j;
j++;
count = 1;
}
}
return max;
}
}
柠檬水找零
在柠檬水摊上,每一杯柠檬水售价5美元,顾客排队购买,一次一杯。每位顾客只买一杯柠檬水,然后像你付5美元、10美元或者20美元,必须正确给每个顾客找零,注意一开始你手头没有任何零钱。如果你可以给每位顾客找零返回true,否则返回false。
实现
package test;
public class lemonChange {
public static void main(String[] args) {
System.out.println(change(new int[] {5,5,10}));
}
public static boolean change(int[] bills) {
int five = 0, ten = 0;
for(int bill : bills) {
if(bill == 5) {
five++;
}else if(bill == 10){
if(five == 0) {
return false;
}
five--;
ten++;
}else if(bill == 20) {
if(five > 0 && ten > 0) {
five--;
ten--;
}else if(five >= 3) {
five -= 3;
}else {
return false;
}
}
}
return true;
}
}
贪心算法
贪心算法主要的思想就是在对问题求解时,总是作出当前最优解的选择。贪心算法适用于每一步的贪心选择最终可以导致问题最优解的情况。