其他:
714. 买卖股票的最佳时机含手续费
学习: 灵茶山艾府题解
问题:
给定一个整数数组 prices
,其中 prices[i]
表示第 i
天的股票价格 ;整数 fee
代表了交易股票的手续费用。
你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。
返回获得利润的最大值。
注意: 这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
思路:
一共有两种状态,有股票和没股票,有股票分为昨天就有和现买,没股票分为昨天就没有或现卖.
手续费用可以并入买或卖任意一个里
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
代码(递推):
class Solution {
public int maxProfit(int[] prices, int fee) {
int f0 = 0;
int f1 = Integer.MIN_VALUE>>2;
for(int i=0;i<prices.length;i++){
int tmp = f0;
f0 = Math.max(f0,f1+prices[i]);
f1 = Math.max(f0-prices[i]-fee,f1);
}
return f0;
}
}
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
代码(递归+记忆化搜索):
class Solution {
int n;
int[] prices;
int fee;
int[][] memory;
int dfs(int i,boolean choose){
if(i<0) return choose?Integer.MIN_VALUE>>2:0;
if(memory[i][(choose?1:0)]!=-1) return memory[i][(choose?1:0)];
if(choose) return memory[i][1]=Math.max(dfs(i-1,true),dfs(i-1,false)-prices[i]);
else return memory[i][0]=Math.max(dfs(i-1,false),dfs(i-1,true)+prices[i]-fee);
}
public int maxProfit(int[] prices, int fee) {
n = prices.length;
memory = new int[n][2];
for(int[] i:memory){
Arrays.fill(i,-1);
}
this.prices = prices;
this.fee = fee;
return dfs(n-1,false);
}
}
337. 打家劫舍 III
跳转: 337. 打家劫舍 III
学习: 灵茶山艾府题解
问题:
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root
。
除了 root
之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root
。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
思路:
一共有两种情况,打劫当前节点和不打劫当前节点.
打劫当前节点最大金额就是不打劫两个子节点的金额之和加上当前节点的金额
不打劫当前节点的最大金额就是两个子节点打劫或不打劫中最大的情况相加
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)(算上栈空间)
代码:
class Solution {
int[] dfs(TreeNode root){
if(root==null) return new int[]{0,0};
int[] left = dfs(root.left);
int[] right = dfs(root.right);
int rob = left[1]+right[1]+root.val;
int notRob = Math.max(left[0],left[1])+Math.max(right[0],right[1]);
return new int[]{rob,notRob};
}
public int rob(TreeNode root) {
int[] res = dfs(root);
return Math.max(res[0],res[1]);
}
}
968. 监控二叉树
跳转: 968. 监控二叉树
学习: 灵茶山艾府题解
问题:
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。
思路:
这题有三种情况,当前节点添加监控,当前节点的至少一个子节点添加监控,当前节点的父节点添加监控.
如果当前节点不添加,那么子节点就只能是自己添加或自己的至少一个子节点添加.
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)(算上栈空间)
代码:
class Solution {
int[] dfs(TreeNode root){
if(root==null){
return new int[]{1001,0,0};
}
int[] left = dfs(root.left);
int[] right = dfs(root.right);
int choose,by_fa,by_children;
choose = Math.min(Math.min(left[0],left[1]),left[2])+Math.min(Math.min(right[0],right[1]),right[2])+1;
by_fa = Math.min(left[0],left[2])+Math.min(right[0],right[2]);
by_children = Math.min(Math.min(left[0]+right[0],left[2]+right[0]),left[0]+right[2]);
return new int[]{choose,by_fa,by_children};
}
public int minCameraCover(TreeNode root) {
int[] ans = dfs(root);
return Math.min(ans[0],ans[2]);
}
}
781. 森林中的兔子
跳转: 781. 森林中的兔子
问题:
森林中有未知数量的兔子。提问其中若干只兔子 “还有多少只兔子与你(指被提问的兔子)颜色相同?” ,将答案收集到一个整数数组 answers
中,其中 answers[i]
是第 i
只兔子的回答。
给你数组 answers
,返回森林中兔子的最少数量。
思路:
只需要尽可能的让说同样数量的兔子结成一组即可,因为题目中数量较小,可以直接使用哈希完成.
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
代码:
class Solution {
public int numRabbits(int[] answers) {
int[] counters = new int[1000];
for(int i:answers){
counters[i]++;
}
int ans = 0;
for(int i=0;i<1000;i++){
if(counters[i]==0) continue;
ans+=(counters[i]+i)/(i+1)*(i+1);
}
return ans;
}
}
总结
今天练习了状态机动规,树形动规,以及哈希