5259. 计算应缴税款总额
https://leetcode.cn/problems/calculate-amount-paid-in-taxes/
思路:简单模拟题,当收入income
大于等于当前税级的上限时,缴纳当前税级上限-上一级税级上限的差值税率;当收入income
小于当前税级的上限时,缴纳收入-上一级税级上限的差值税率,结束;
class Solution {
public double calculateTax(int[][] brackets, int income) {
double ans=0.0;
int pre=0;
for(int[] bracket:brackets) {
int up=bracket[0],per=bracket[1];
if(income<up) {//不满足当前税级 缴纳收入和上一级的上限差
ans+=(income-pre)*per/100.0;
break;
}
ans+=(up-pre)*per/100.0;//满足当前税级 缴纳当前上限和上一级的上限差
pre=up;
}
return ans;
}
}
5270. 网格中的最小路径代价
https://leetcode.cn/problems/minimum-path-cost-in-a-grid/
思路:动态规划,状态转化方程为:
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
d
p
[
i
−
1
]
[
k
]
+
g
r
i
d
[
[
i
]
[
j
]
+
m
o
v
e
c
o
s
t
[
g
r
i
d
[
i
−
1
]
[
k
]
]
[
j
]
)
dp[i][j]=min(dp[i][j],dp[i-1][k]+grid[[i][j]+movecost[grid[i-1][k]][j])
dp[i][j]=min(dp[i][j],dp[i−1][k]+grid[[i][j]+movecost[grid[i−1][k]][j])
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示以
g
r
i
d
[
i
]
[
j
]
grid[i][j]
grid[i][j]结尾的路径的最小值
k的取值有n个,n是列数, d p [ i − 1 ] [ k ] dp[i-1][k] dp[i−1][k]表示到达上一行的某个位置需要的代价
class Solution {
public int minPathCost(int[][] grid, int[][] moveCost) {
int m=grid.length,n=grid[0].length;
int[][] dp=new int[m][n];
for(int i=0;i<m;i++){
Arrays.fill(dp[i],Integer.MAX_VALUE);
}
for(int j=0;j<n;j++){
dp[0][j]=grid[0][j];//第一行的代价就是单元格值之和
}
for(int i=1;i<m;i++){
for(int j=0;j<n;j++){
for(int k=0;k<n;k++){
dp[i][j]=Math.min(dp[i][j],dp[i-1][k]+grid[i][j]+moveCost[grid[i-1][k]][j]);
}
}
}
int ans=Integer.MAX_VALUE;
for(int j=0;j<n;j++){//找出最后一行中的最小值
ans=Math.min(ans,dp[m-1][j]);
}
return ans;
}
}
5289. 公平分发饼干
https://leetcode.cn/problems/fair-distribution-of-cookies/
思路:DFS,枚举出每一种分配方案,n包饼干,k个孩子,分配方案一共有 k n k^n kn种,当然在枚举的过程中可以进行剪枝,如果当前正在计算的方案中目前计算到的最大不公平度已经大于等于之前某个答案ans, 本次方案的计算可以结束,因为不会得到一个更优的答案
class Solution {
int ans=Integer.MAX_VALUE;
public int distributeCookies(int[] cookies, int k) {
int[] sum=new int[k];
dfs(cookies,k,sum,0,0,cookies.length);
return ans;
}
/*
* max:当前分配给某个孩子的饼干最大数量
*/
public void dfs(int[] cookies, int k,int[] sum,int index,int max,int n){
if(max>=ans){//某种分配方案中已经出现最大分配数量大于之前的一个答案ans 说明这种方案不可能出现比ans更优的值
return;
}
if(index==n){//更新某种分配方案下的ans
ans=max;
return;
}
for(int i=0;i<k;i++){
sum[i]+=cookies[index];//第index包饼干给孩子i
dfs(cookies,k,sum,index+1,Math.max(sum[i],max),n);
sum[i]-=cookies[index];//回溯
}
}
}
6094. 公司命名
https://leetcode.cn/problems/naming-a-company/
思路:对于ideas中的名字,按照以下规则进行分组: 去掉首字母,剩余的部分相同的为一组,比如abc bbc cbc
,则bc
组对应的首字母为a b c
, 为了方便统计每一组的首字母是哪些,可以采用比特位计数的方法,a b c
的话就对应0111
。当选择的两个名字交换首字母后不会出现在列表中,则这两个名字可以进行组合,由于没有规定谁前谁后,因此有2种答案。
用cnt[i][j]
表示含有字母i但是不含有字符j的分组的个数,遍历每一组,改组对应的首字母必定是26个字母中的若干个,如果某个字母出现在该组对应的首字母集合中,则计算出cnt[i][j]
的值,如果某个字母没有出现在该组对应的首字母集合中, 就加上互补的cnt[i][j]
的值
class Solution {
public long distinctNames(String[] ideas) {
HashMap<String,Integer> group=new HashMap<>();
for(String idea:ideas){
String str=idea.substring(1);//[1:n-1]
group.put(str,group.getOrDefault(str,0)|1<<idea.charAt(0)-'a');
}
long ans=0;
int[][] cnt=new int[26][26];
//cnt[i][j]: 首字母中不包含i但是包含j的组的个数
for(Integer mask:group.values()){
for(int i=0;i<26;i++){
if((mask>>i&1)==0){//不包含i
for(int j=0;j<26;j++){
if((mask>>j&1)>0){//包含j
++cnt[i][j];
}
}
}else{//首字母集合包含i
for(int j=0;j<26;j++){
if((mask>>j&1)==0){//首字母不包含j
ans+=cnt[i][j];//当前case: 包含i但是不包含j 需要的组:不包含i但是包含j的组的数量 即cnt[i][j]
}
}
}
}
}
return ans*2;//返回2倍数量 因为两个单词的排列顺序有两种
}
}