LeetCode第297场周赛(20220612)

本文涵盖了四道LeetCode算法题目,分别是计算应缴税款总额、网格中的最小路径代价、公平分发饼干和公司命名问题。通过模拟、动态规划、深度优先搜索和比特位计数等方法解决实际问题,展示了在不同场景下如何运用算法解决问题。
摘要由CSDN通过智能技术生成

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[i1][k]+grid[[i][j]+movecost[grid[i1][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[i1][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倍数量  因为两个单词的排列顺序有两种
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodePanda@GPF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值