代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果

简介: 代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果

1. LeetCode 1005. K 次取反后最大化的数组和

1.1 思路

  1. 本题有两次贪心的选择,第一次贪心在优先对负数取反,再优先对绝对值大的负数取反。第二次贪心是此时若数组里都是非负数时就对最小的非负数进行取反
  2. 全局最优:得到数组的最大数组和。找不出明显反例反驳
  3. 首先对数组排序,我们要自己实现按照绝对值从大到小排序。然后遍历数组,for(int i=0; i<nums.length; i++)if(nums[i]<0&&k>0)优先对绝对值大的负数取反,nums[i]=-nums[i],k--。这里就是完成了第一次贪心的策略
  4. 此时数组都是非负数了,可能 k 还没用完,接下来就优先对最小的非负数取反。if(k%2==1)nums[nums.length-1]=-nums[nums.length-1]。注意这里数组还是按照绝对值从大到小排序的。这里 k 是奇数就取反,如果是偶数无所谓,因为偶数次取反,非负数还是非负数
  5. 以上这么写性能很好

1.2 代码

//
class Solution {
    public int largestSumAfterKNegations(int[] nums, int K) {
      // 将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
  nums = IntStream.of(nums)
         .boxed()
         .sorted((o1, o2) -> Math.abs(o2) - Math.abs(o1))
         .mapToInt(Integer::intValue).toArray();
  int len = nums.length;      
  for (int i = 0; i < len; i++) {
      //从前向后遍历,遇到负数将其变为正数,同时K--
      if (nums[i] < 0 && K > 0) {
        nums[i] = -nums[i];
        K--;
      }
  }
  // 如果K还大于0,那么反复转变数值最小的元素,将K用完
  if (K % 2 == 1) nums[len - 1] = -nums[len - 1];
  return Arrays.stream(nums).sum();
    }
}

2. LeetCode 134. 加油站

2.1 思路


  1. 本题虽然是一维数组但是是首尾相连的
  2. 这题有补充有消耗,应该关注的是有补充有消耗之后油箱还剩多少油,最终对油箱的油量是增加还是消耗的作用。通过 gas[i]-cost[i] 得到净剩油的数组,这里定义个 curSum 统计我们每一个站点剩余的油量,一旦为负数了就选择下一个站点(i+1)开始。贪心思路:不断累加剩余的油量,一旦在某个站点 curSum 为负数了,说明这个站点(i)之前每个站点作为其实位置都是不行的,因此选择下一个站点(i+1)为起始位置,继续向后遍历。这里有疑问,为什么这个 i 之前的所有位置作为起始位置都是不行的。假设区间 2 的和 curSum>0,从这里开始,区间 1 的和加上区间 2 的和就是 curSum 此时<0,如果区间 2 的和>0,那么区间 1 的和就是<0,那么按照上面的规则就应该是从区间 2 作为起点往后继续累加了

  3. 局部最优:当前累加剩余数组 rest[i] 的和 curSum 一旦小于 0,起始位置至少要是 i+1,因为从 i 之前开始一定不行。
  4. 全局最优:找到可以跑一圈的起始位置。
  5. 定义个 curSum 统计从头开始每一站的剩余油量,totalSum 把所有剩余油量加起来如果<0,说明从任何一个位置跑的话都不可能跑完一圈,定义个 start,如果 curSum<0 就从 i+1 开始
  6. for(int i=0; i<gas.length; i++)curSum+=(gas[i]-cost[i]),totalSum+=(gas[i]-cost[i]),if(curSum<0)start=i+1,并且 curSum=0 重新开始统计。
  7. 退出循环后 if(totalSum<0)return -1;最后 return start 即可
  8. 按照这个思路到最后一个位置的时候已经可以确定没有结果了

2.2 代码

//
// 解法2
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int curSum = 0;
        int totalSum = 0;
        int index = 0;
        for (int i = 0; i < gas.length; i++) {
            curSum += gas[i] - cost[i];
            totalSum += gas[i] - cost[i];
            if (curSum < 0) {
                index = (i + 1) % gas.length ; 
                curSum = 0;
            }
        }
        if (totalSum < 0) return -1;
        return index;
    }
}

3. LeetCode 135. 分发糖果

3.1 思路

  1. 每个小孩至少 1 个糖果,得分高的小孩比旁边低分的糖果要多糖果,但最终是求最少的给糖果数量
  2. 我们的难题是要和两边的小孩一起进行比较。不少题都有这种情况,两边一起比较就很容易乱,这种题解题思路一定是先确定一边再确定另一边。
  3. 首先先看情况 1:右边比左边得分高,if(rating[i-1]<rating[i]) 这个 candy[i]=candy[i-1]+1。这就是右边比左边得分高的处理方式。注意这里是从左向右遍历
  4. 情况 2:左边比右边高,注意这里是从右向左遍历,为什么?因为这种情况如果从左向右遍历是无法使用到情况 1 处理的结果的,因为比较依赖第 i+1 个元素。 if(rating[i]>rating[i+1]) 这个 candy[i]=canddy[i+1]+1,由于情况 1 也算了个 candy[i] 我们要在两者间取个值,我们此时如果这个孩子得分比较高是要既比左边大又要比右边大的,因此要比较求最大值,所以实际上 candy[i]=Math.max(candy[i+1]+1,candy[i]),算完以后 candy[i] 就是每个小孩子应得的糖果数,最后累加就是我们要求的结果
  5. 定义数组 candy,candy[0]=1;情况 1 for(int i=1;i<rating.length; i++) 从 1 开始是因为最开始是从 i 和 i-1 比较,if(rating[i-1]<rating[i-1])candy[i]=candy[i-1]+1,否则就是 candy[i]=1;
  6. 情况 2 for(int i=rating.length-2; i>=0; i--),从这个位置开始是因为 rating.length-1 是最后一个位置,而最开始是最后一个位置和倒数第二个位置比较,即 i(倒数第二) 和 i+1(最后一个),if(rating[i]>rating[i+1]) candy[i]=Math.max(candy[i+1]+1,candy[i])
  7. 最后定义个 result 累加 candy 数组,然后返回 result 即可

3.2 代码

//
class Solution {
    /**
         分两个阶段
         1、起点下标1 从左往右,只要 右边 比 左边 大,右边的糖果=左边 + 1
         2、起点下标 ratings.length - 2 从右往左, 只要左边 比 右边 大,此时 左边的糖果应该 取本身的糖果数(符合比它左边大) 和 右边糖果数 + 1 二者的最大值,这样才符合 它比它左边的大,也比它右边大
    */
    public int candy(int[] ratings) {
        int len = ratings.length;
        int[] candyVec = new int[len];
        candyVec[0] = 1;
        for (int i = 1; i < len; i++) {
            candyVec[i] = (ratings[i] > ratings[i - 1]) ? candyVec[i - 1] + 1 : 1;
        }
        for (int i = len - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candyVec[i] = Math.max(candyVec[i], candyVec[i + 1] + 1);
            }
        }
        int ans = 0;
        for (int num : candyVec) {
            ans += num;
        }
        return ans;
    }
}
目录
打赏
0
0
0
0
9
分享
相关文章
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
这个AI把arXiv变成代码工厂,快速复现顶会算法!Paper2Code:AI论文自动转代码神器,多智能体框架颠覆科研复现
Paper2Code是由韩国科学技术院与DeepAuto.ai联合开发的多智能体框架,通过规划、分析和代码生成三阶段流程,将机器学习论文自动转化为可执行代码仓库,显著提升科研复现效率。
364 19
这个AI把arXiv变成代码工厂,快速复现顶会算法!Paper2Code:AI论文自动转代码神器,多智能体框架颠覆科研复现
18个常用的强化学习算法整理:从基础方法到高级模型的理论技术与代码实现
本文系统讲解从基本强化学习方法到高级技术(如PPO、A3C、PlaNet等)的实现原理与编码过程,旨在通过理论结合代码的方式,构建对强化学习算法的全面理解。
188 10
18个常用的强化学习算法整理:从基础方法到高级模型的理论技术与代码实现
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
基于WOA鲸鱼优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于MATLAB 2022a/2024b实现,采用WOA优化的BiLSTM算法进行序列预测。核心代码包含完整中文注释与操作视频,展示从参数优化到模型训练、预测的全流程。BiLSTM通过前向与后向LSTM结合,有效捕捉序列前后文信息,解决传统RNN梯度消失问题。WOA优化超参数(如学习率、隐藏层神经元数),提升模型性能,避免局部最优解。附有运行效果图预览,最终输出预测值与实际值对比,RMSE评估精度。适合研究时序数据分析与深度学习优化的开发者参考。
基于GA遗传优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本内容包含基于BiLSTM与遗传算法(GA)的算法介绍及实现。算法通过MATLAB2022a/2024b运行,核心为优化BiLSTM超参数(如学习率、神经元数量),提升预测性能。LSTM解决传统RNN梯度问题,捕捉长期依赖;BiLSTM双向处理序列,融合前文后文信息,适合全局信息任务。附完整代码(含注释)、操作视频及无水印运行效果预览,适用于股票预测等场景,精度优于单向LSTM。
基于PSO粒子群优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于MATLAB2022a/2024b开发,结合粒子群优化(PSO)算法与双向长短期记忆网络(BiLSTM),用于优化序列预测任务中的模型参数。核心代码包含详细中文注释及操作视频,涵盖遗传算法优化过程、BiLSTM网络构建、训练及预测分析。通过PSO优化BiLSTM的超参数(如学习率、隐藏层神经元数等),显著提升模型捕捉长期依赖关系和上下文信息的能力,适用于气象、交通流量等场景。附有运行效果图预览,展示适应度值、RMSE变化及预测结果对比,验证方法有效性。
基于遗传算法的256QAM星座图的最优概率整形matlab仿真,对比优化前后整形星座图和误码率
本内容展示了基于GA(遗传算法)优化的256QAM概率星座整形(PCS)技术的研究与实现。通过Matlab仿真,分析了优化前后星座图和误码率(BER)的变化。256QAM采用非均匀概率分布(Maxwell-Boltzman分布)降低外圈星座点出现频率,减小平均功率并增加最小欧氏距离,从而提升传输性能。GA算法以BER为适应度函数,搜索最优整形参数v,显著降低误码率。核心程序实现了GA优化过程,包括种群初始化、选择、交叉、变异等步骤,并绘制了优化曲线。此研究有助于提高频谱效率和传输灵活性,适用于不同信道环境。
48 10
基于遗传优化ELM网络的时间序列预测算法matlab仿真
本项目实现了一种基于遗传算法优化的极限学习机(GA-ELM)网络时间序列预测方法。通过对比传统ELM与GA-ELM,验证了参数优化对非线性时间序列预测精度的提升效果。核心程序利用MATLAB 2022A完成,采用遗传算法全局搜索最优权重与偏置,结合ELM快速训练特性,显著提高模型稳定性与准确性。实验结果展示了GA-ELM在复杂数据中的优越表现,误差明显降低。此方法适用于金融、气象等领域的时间序列预测任务。
|
28天前
|
基于遗传优化算法的带时间窗多车辆路线规划matlab仿真
本程序基于遗传优化算法,实现带时间窗的多车辆路线规划,并通过MATLAB2022A仿真展示结果。输入节点坐标与时间窗信息后,算法输出最优路径规划方案。示例结果包含4条路线,覆盖所有节点并满足时间窗约束。核心代码包括初始化、适应度计算、交叉变异及局部搜索等环节,确保解的质量与可行性。遗传算法通过模拟自然进化过程,逐步优化种群个体,有效解决复杂约束条件下的路径规划问题。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问