题目二

题目描述

5690. 最接近目标价格的甜点成本  难度:中等-中等

题解

解法一:三进制状态压缩

  考虑到baseCosts、toppingCosts的长度最多都为10,每一种辅料都有加0、1、2份的选择,因此可以考虑三进制状态压缩求解。类似二进制的状态压缩。

以10种辅料为例。

直到curJ为0。

代码:

 1 class Solution {
2 public int closestCost(int[] baseCosts, int[] toppingCosts, int target) {
3 Arrays.sort(baseCosts);
4 Arrays.sort(toppingCosts);
5 int nearestCost=0;//记录最接近的成本
6 int minGap = Integer.MAX_VALUE;//记录目前最接近的成本和目标成本target的差
7 for(int i=0;i<baseCosts.length;i++){//每一种基料
8 for(int j=0;j<Math.pow(3,toppingCosts.length);j++){//三进制位串
9 int cost = baseCosts[i];
10 int curJ = j;//现在的位串
11 int index = 0;
12 while(curJ!=0){//取位串的每一位
13 int curBit = curJ % 3;//位串的当前一位
14 curJ /= 3;
15 cost += toppingCosts[index]*curBit;
16 index++;
17 }
18 if(Math.abs(cost-target)==0){//若现在的成本恰好是target,直接返回
19 return target;
20 }else if(Math.abs(cost-target)<minGap){//若目前的成本更接近target,更新nearestCost和minGap;
21 minGap = Math.abs(cost-target);
22 nearestCost = cost;
23 }else if(Math.abs(cost-target)==minGap){//若目前的成本和已经找到的最接近成本与目标成本的差距相等,取成本较小者(题目要求)
24 if(cost<nearestCost){
25 nearestCost = cost;
26 }
27 }
28 }
29 }
30 return nearestCost;
31 }
32 }

略微优化代码:

  当目前的cost>target 且 Math.abs(cost-target)>minGap时,由于cost随着位串的遍历单调不减,这种方案可以不再考虑,肯定不优于已经求得的成本,因此可以剪枝。

  

 1 class Solution {
2 public int closestCost(int[] baseCosts, int[] toppingCosts, int target) {
3 Arrays.sort(baseCosts);
4 Arrays.sort(toppingCosts);
5 int nearestCost=Integer.MAX_VALUE;//记录最接近的成本
6 int minGap = Integer.MAX_VALUE;//记录目前最接近的成本和目标成本target的差
7 for(int i=0;i<baseCosts.length;i++){//每一种基料
8 for(int j=0;j<Math.pow(3,toppingCosts.length);j++){//三进制位串
9 int cost = baseCosts[i];
10 int curJ = j;//现在的位串
11 int index = 0;
12 boolean isCut = false;
13 while(curJ!=0){//取位串的每一位
14 int curBit = curJ % 3;//位串的当前一位
15 curJ /= 3;
16 cost += toppingCosts[index]*curBit;
17 index++;
18 if(cost>target&&Math.abs(cost-target)>minGap){//剪枝
19 isCut = true;
20 break;
21 }
22 }
23 if(isCut==true){//剪枝
24 continue;
25 }
26 if(Math.abs(cost-target)==0){//若现在的成本恰好是target,直接返回
27 return target;
28 }else if(Math.abs(cost-target)<minGap){//若目前的成本更接近target,更新nearestCost和minGap;
29 minGap = Math.abs(cost-target);
30 nearestCost = cost;
31 }else if(Math.abs(cost-target)==minGap){//若目前的成本和已经找到的最接近成本与目标成本的差距相等,取成本较小者(题目要求)
32 if(cost<nearestCost){
33 nearestCost = cost;
34 }
35 }
36 }
37 }
38 return nearestCost;
39 }
40 }

解法二:动态规划

本题数据范围很小,暴力枚举辅料组合就可以通过,但时间复杂度为指数级。

把问题转化为背包问题,可以将时间复杂度降低到多项式级别。

  • 因为每种辅料最多可以用两次,所以直接把每种辅料变成两个。
  • 基料必须且只能选一种,可以首先处理好。

题目三

题目描述

5691. 通过最少操作次数使数组的和相等 难度:中等-中等

题解-贪心法

看到题目后,总结出以下要点:

  • 总和大的数组中元素减小等同于总和小的数组中元素增大(这样转化后,我们在求得每个数组的总和后,两个总和不再狭义地代表每个数组的总和)
  • 要实现最小操作次数,考虑从最小的元素开始增大,增大到最大,如1直接变成6;或从最大的元素开始减小,减小到最小,如6直接变成1。
  • 如何判断是否已经满足条件呢?既然我们是保证每次改变量都是最大,那么,如果这次改变后,最好是两个总和相等,那么功德圆满,即使不相等,但若实现了两个总和的反转(即大小关系反转),那么因为我们是最大的改变量,我们只需在心中将这次的改变量减小一点,如原来是2直接到6,我们可以改变2到5、4等等,肯定能实现两个总和的相等。
  • 题目中固定1-6的数据范围,我们可以指定一个大小为6的数组inc[] (为了方便,inc[0]不用),inc[1]代表两个数组中1或6的个数(总和大的数组中的1可以增大到6、总和小的数组中的6可以减小到1),inc[2]代表两个数组中2或5的个数(总和大的数组中的2可以增大到6、总和小的数组中的5可以减小到1)
 1 class Solution {
2 public int minOperations(int[] nums1, int[] nums2) {
3 if(Math.min(nums1.length,nums2.length)*6<Math.max(nums1.length,nums2.length)*1){
4 return -1;
5 }
6 int nums1Sum = 0;
7 int nums2Sum = 0;
8 for(int i=0;i<nums1.length;i++){//统计nums1的和
9 nums1Sum += nums1[i];
10 }
11 for(int i=0;i<nums2.length;i++){//统计nums2的和
12 nums2Sum += nums2[i];
13 }
14 if(nums1Sum==nums2Sum){
15 return 0;
16 }
17 int[] inc = new int[6];//统计nums1 和 nums2中可以增大或减小的数的个数,即1 ~ 5的个数;为了方便,数组容量多1,inc[0]不用
18 if(nums1Sum<nums2Sum){
19 for(int i=0;i<nums1.length;i++){//nums1Sum较小,考虑nums1中可以增大的数
20 if(nums1[i]<6){ // 1 ~ 5
21 inc[nums1[i]]++;
22 }
23 }
24 for(int i=0;i<nums2.length;i++){//nums2Sum较大,考虑nums2中可以减小的数
25 if(nums2[i]>1){ // 2 ~ 6 nums2减小相当于nums1增大,如6减小到1,同1增加到6t;又如5减小到1同2增加到6
26 inc[7-nums2[i]]++;
27 }
28 }
29 int cnt=0;
30 for(int i=1;i<=5;i++){//此后的nums1Sum已经不是真正意义上的nums1的和
31 while(inc[i]!=0){
32 nums1Sum += 6 - i;
33 inc[i]--;
34 cnt++;
35 if(nums1Sum>=nums2Sum){
36 return cnt;
37 }
38 }
39 }
40 }else if(nums1Sum>nums2Sum){
41 for(int i=0;i<nums2.length;i++){//nums2Sum较小,考虑nums2中可以增大的数
42 if(nums2[i]<6){ // 1 ~ 5
43 inc[nums2[i]]++;
44 }
45 }
46 for(int i=0;i<nums1.length;i++){//nums1Sum较大,考虑nums1中可以减小的数
47 if(nums1[i]>1){ // 2 ~ 6 nums1减小相当于nums2增大,如6减小到1,同1增加到6;又如5减小到1同2增加到6
48 inc[7-nums1[i]]++;
49 }
50 }
51 int cnt=0;
52 for(int i=1;i<=5;i++){
53 while(inc[i]!=0){
54 nums2Sum += 6 - i;
55 inc[i]--;
56 cnt++;
57 if(nums2Sum>=nums1Sum){
58 return cnt;
59 }
60 }
61 }
62 }
63 return -1;
64 }
65 }

题目三

题目描述

5691. 通过最少操作次数使数组的和相等  难度:困难-简单

题解

230th Weekly Leetcode Contest的更多相关文章

  1. LeetCode Contest 166

    LeetCode Contest 166 第一次知道LeetCode 也有比赛. 很久没有打过这种线上的比赛,很激动. 直接写题解吧 第一题 很弱智 class Solution { public: ...

  2. leetcode contest 20

    Q1: 520. Detect Capital Given a word, you need to judge whether the usage of capitals in it is right ...

  3. leetcode bugfree note

    463. Island Perimeterhttps://leetcode.com/problems/island-perimeter/就是逐一遍历所有的cell,用分离的cell总的的边数减去重叠的 ...

  4. [LeetCode] Reverse Words in a String III 翻转字符串中的单词之三

    Given a string, you need to reverse the order of characters in each word within a sentence while sti ...

  5. C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  6. LeetCode算法题-Reverse Words in a String III(Java实现)

    这是悦乐书的第259次更新,第272篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第126题(顺位题号是557).给定一个字符串,您需要反转句子中每个单词中的字符顺序,同 ...

  7. Leetcode#557. Reverse Words in a String III(反转字符串中的单词 III)

    题目描述 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. 示例 1: 输入: "Let's take LeetCode contest" 输 ...

  8. 【leetcode】557. Reverse Words in a String III

    Algorithm [leetcode]557. Reverse Words in a String III https://leetcode.com/problems/reverse-words-i ...

  9. leetCode 557. Reverse Words in a String I

    Input: "Let's take LeetCode contest" Output: "s'teL ekat edoCteeL tsetnoc" 解:输入一 ...

随机推荐

  1. zabbix监控之用户及用户组

    一.概述 Zabbix 中的所有用户都通过 Web 前端去访问 Zabbix 应用程序.并为每个用户分配唯一的登陆名和密码. 所有用户的密码都被加密并储存于 Zabbix 数据库中.用户不能使用其用户 ...

  2. 003.kubernets对于namespace的管理

    一 Kuberbetes的架构简单介绍 1.1 云计算的传统分类 1.2 kubernetes基础架构 工作机制 用户通过kubectl向api-server提交需要运行的pod描述 api-serv ...

  3. 记一次MySQL(5.7版本)数据库的主从同步和备份

    我遇到的问题 我先后在BAT三大云服务器商购买了学生机,配置如下 百度云2核/4G 阿里云1核/2G 腾讯云1核/2G 我的解决方案 由于我不知道百度云的续费规则,导致买了2核/4G的服务器之后以为像 ...

  4. python基础之字典、集合

    一.字典(dictionary) 作用:存多个值,key-value存取,取值速度快 定义:key必须是不可变类型,value可以是任意类型 字典是一个无序的,可以修改的,元素呈键值对的形式,以逗号分 ...

  5. HEVC之路0:HM16.18的运行+码流分析

    1.HM下载 HM不能直接网页下载,因为它是采用svn来管理代码的,因此需要利用svn下载,这里采用TortoiseSVN(软件下载地址为https://tortoisesvn.net/)进行下载. ...

  6. .Net之简单通知服务

    开篇语 这两天看见有大佬分享使用钉钉和企业微信的机器人来做通知报警,然后我想到了我使用的另一个第三方软件捷易快信(可能大家都不知道这个东西,我也忘了我最开始是咋知道的),该服务的优点是可以通过微信进行 ...

  7. 如何在TVM上集成Codegen(下)

    如何在TVM上集成Codegen(下) Bring DNNL to TVM: JSON Codegen/Runtime 现在实现将中继图序列化为JSON表示的DNNL codegen,然后实现DNNL ...

  8. CodeGen标记循环

    CodeGen标记循环 标记循环是一个模板文件构造,它允许您迭代CodeGen拥有的标记信息的集合.为了使用标记循环,必须基于至少定义了一个字段标记的存储库结构生成代码.              标 ...

  9. Appium_Android自动化测试Genymotion之模拟器联网设置

    目的: 使用Genymotion做Android项目,需要考虑到联网,以下是设置操作 操作步骤: 打开VM VirtualBox,设置->网络-> 启动模拟器,设置  备注: 模拟器的手机 ...

  10. Python_selenium PO模式下 Tesecase 的相同执行代码做成selenium_base_case公共模块及调用

    作用: PO模式下 Tesecase 的相同执行代码做成selenium_base_case公共模块及调用,提高代码简洁度,实现同样效果. 框架结构: 代码简单实践: common模块下 seleni ...