当前位置: 首页 > news >正文

力扣.870优势洗牌解决方法: 下标排序​编辑力扣.942增减字符串匹配最长回文子序列牛客.背包问题(最大体积)力扣.45跳跃游戏II 另一种思考

目录

力扣.870优势洗牌

解决方法: 下标排序​编辑

力扣.942增减字符串匹配

最长回文子序列

牛客.背包问题(最大体积)

力扣.45跳跃游戏II

 另一种思考


力扣.870优势洗牌

对两个进行排序

难点:排序后,如何找到之前的顺序,进行返回呢

解决方法: 下标排序

通过下标来查找,

然后定义left和right指针,假如比他大就正常给left,否则移动到right里面

感觉下标排序常用,但是不好想。

index[left]就是当前从小到大的下标,也相当于排序,但是不改变原数组

所以相当于从原数组里面排序了找,从小到大找,然后用看是否大于当前值,大于,直接给ret[[]]对应的下标值++,否则给right赋值,就是给最大的那些数

class Solution {public static int[] advantageCount(int[] nums1, int[] nums2) {int n = nums1.length;//两个进行排序Integer[] index = new Integer[n];for (int i = 0; i < n; i++) {index[i] = i;}//numsB排序后的第一个//排序下标数组Arrays.sort(nums1);//从大到小的下标,根据下标进行排序Arrays.sort(index, (i, j) -> {return nums2[i] - nums2[j];});//0 1 2 2 4//1 3 0 0 2//[2 3 0 4 1]int[] ret = new int[n];int left = 0;int right = n - 1;//从nums1遍历for (int x : nums1) {if (x > nums2[index[left]]) {ret[index[left++]] = x;} else {//比不过ret[index[right--]] = x;}}return ret;}
}

力扣.942增减字符串匹配

假如当前是I,就是上升的趋势,我直接取最小值上升,假如是d,就是下降的趋,我取最大值下降,为啥是正确的呢?假如当前是I,那么就要给他安排最小的,因为假如上升趋势

I [ ]框里面的每个都是上升趋势,假如d[] 框里面每个都是下降趋势

 public int[] diStringMatch(String s) {int n=s.length();//0-nint[]ret=new int[n+1];int left=0;int right=n;for(int i=0;i<n;i++){if(s.charAt(i)=='I'){//向上的趋势ret[i]=left++;}else{ret[i]=right--;}}ret[n]=left++;return ret;}

最长回文子序列

看到回文,子序列有点没反应过来,有试过一维dp,忘了二维dp怎么写了,

class Solution {public int longestPalindromeSubseq(String s) {
//dp[i][j]:从i位置到j区间内的最长回文子序列
//dp[i][j]=dp[i+1][j-1]+2;
//dp[i][j]=max(dp[i+1][j],dp[i][j-1])
//dp[0][0]:0->0=1 dp[0][1]=
//dp[] i<j 从左往右,上半图 返回最大值int n=s.length();char[]ss=s.toCharArray();int[][]dp=new int[n][n];dp[0][0]=1;dp[n-1][n-1]=1;for(int i=n-1;i>=0;i--){for(int j=i;j<n;j++){if(ss[i]==ss[j]){if(i==j) dp[i][j]=1;else{dp[i][j]=dp[i+1][j-1]+2;}}else {dp[i][j]=Math.max(dp[i+1][j],dp[i][j-1]);}}}return dp[0][n-1];}
}

牛客.背包问题(最大体积)

跟我想的基本一样,就是到达i位置的时候,总体积不超过是j,然后剩余空间最小的dp[i][j].

这个的缺点就是需要进行初始化,因为最开始我的剩余体积是24

import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {//背包问题public static void main(String[] args) {Scanner in = new Scanner(System.in);int V=in.nextInt();int n=in.nextInt();int[]a=new int[n+1];for(int i=1;i<=n;i++){a[i]=in.nextInt();}//到达i位置时,空间为j,是剩余空间最小int[][]dp=new int[n+1][V+1];//第0个位置,此时的剩余空间是Vdp[0][V]=V;int min=V;Arrays.fill(dp[0],V);//在第一个开始时候,空间是Vfor(int i=1;i<=n;i++){for(int j=V;j>=0;j--){//塞不进去,保持不动就好dp[i][j]=dp[i-1][j];if(j-a[i]>=0){//此时说明我还能塞,或者看我能不能塞下dp[i][j]=Math.min(dp[i-1][j],dp[i-1][j-a[i]]-a[i]);}min=Math.min(min,dp[i][j]);}}System.out.print(min);}
}

这个的优点就很明显,不用去初始化,但是结果需要自己处理,总结就是二者都可以

import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {//背包问题public static void main(String[] args) {Scanner in = new Scanner(System.in);int V=in.nextInt();int n=in.nextInt();int[]a=new int[n+1];for(int i=1;i<=n;i++){a[i]=in.nextInt();}//到达i位置时,空间为j,是剩余空间最小int[][]dp=new int[n+1][V+1];//第0个位置,此时的剩余空间是Vint max=0;// Arrays.fill(dp[0],V);//在第一个开始时候,空间是Vfor(int i=1;i<=n;i++){for(int j=V;j>=0;j--){//塞不进去,保持不动就好dp[i][j]=dp[i-1][j];if(j-a[i]>=0){//此时说明我还能塞,或者看我能不能塞下dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-a[i]]+a[i]);}max=Math.max(max,dp[i][j]);}}System.out.print(V-max);}
}

力扣.45跳跃游戏II

假如用动态规划做

//到达i位置时候最小的跳跃次数

dp[i]

转移方程不是常见的那种,要去检测

从0-i-1位置中,能到达i位置

从j开始遍历 0-j j<i;j++

dp[i]=dp[j]+1;开始,第一次,后面的时候dp[i]!=0的时候,就去比较,这么多次dp[j]+1的最小值

class Solution {public int jump(int[] nums) {int n=nums.length;int[]dp=new int[n];dp[0]=0;//到达i位置时候最小的跳跃次数for(int i=1;i<n;i++){for(int j=0;j<i;j++){if(j+nums[j]>=i){if(dp[i]!=0) dp[i]=Math.min(dp[j]+1,dp[i]);else  dp[i]=dp[j]+1;}}}return dp[n-1];
}
}

贪心

class Solution {public static int jump(int[] a) {int n=a.length;int count=1;if(n==1)return 0;else if(a[0]>=n-1)return 1;for(int i=0;i<n;){//从i+1开始遍历int left=i+1;//右边界int right=a[i]+i;int max=0;//表示下一轮下标的值int j=0;//统计新一轮的值while(left<n&&left<=right){if(max<left+a[left]){j=left;max=left+a[left];}left++;}count++;//i取当前位置能跳的最远的值i=j;if(max>=n-1)break;}return count;}
}

 另一种思考

dp[i][j]:从前i个数中挑选,所有做法中,能否凑成j这个数字-true/false

状态转移方程

dp[i][j]=     不选i        dp[i-1][j]

                    选i        dp[i-1][j-a[i]]         两个取||为判断是否能凑成这个数字

初始化,假如前不管几个,我都不选,那么我都【i】count都为true;

import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n=in.nextInt();int[]a=new int[n+1];int count=0;for(int i=1;i<=n;i++){a[i]=in.nextInt();count+=a[i];} if(count%2!=0){System.out.print(false);}else{count=count/2;int ret=0;boolean[][]dp=new boolean[n+1][count+1];for(int i=0;i<=n;i++)dp[i][0]=true;//前i个物品中,最大体积//dp[i][j]=-1表示没有这种情况for(int i=1;i<=n;i++){for(int j=0;j<=count;j++){dp[i][j]=dp[i-1][j];if(j-a[i]>=0){//指当前体积+a[i];dp[i][j]=dp[i][j]||dp[i-1][j-a[i]];}//状态,假如当前不存在和存在两种}}if(dp[n][count]==true) System.out.print(true);else System.out.print(false);}}
}

http://www.dtcms.com/a/327388.html

相关文章:

  • 数据结构——线性表(核心操作,附代码)
  • vue项目封装axios请求,支持判断当前环境及判断token是否过期等等(详细教程,可复制粘贴代码)
  • cuda排序算法--双调排序(Bitonic_Sort)
  • 【数据库】 MySQL 表的操作详解
  • 蓝桥杯手算题和杂题简易做法
  • 《Auracast广播音频技术解析及未来路线图》 —蓝牙技术联盟 市场拓展经理 吴志豪 技术与市场经理 鲁公羽
  • 基于 DiT 大模型与字体级分割的视频字幕无痕擦除方案,助力短剧出海
  • 深度学习与遥感入门(六)|轻量化 MobileNetV2 高光谱分类
  • 4.7 GB 视频导致浏览器内存溢出(OOM)的解决方案
  • 从零部署Nacos:替代Eureka的服务注册与服务发现基础教程
  • 视频输入输出模块介绍和示例
  • Dubbo 3.x源码(33)—Dubbo Consumer接收服务调用响应
  • Python day42
  • tensorrt-llm0.20.0离线部署DeepSeek-R1-Distill-Qwen-32B
  • 第六十三章:AI模型的“跨界之旅”:不同硬件架构下的兼容性方案
  • Linux NAPI 实现机制深度解析
  • 【CDA 新一级】学习笔记第1篇:数据分析的时代背景
  • 【前端八股文面试题】【JavaScript篇7】什么是JavaScript的原型、原型链? 有什么特点
  • 【设计模式精解】Java实现责任链模式(职责链模式)优雅处理多级请求(概述,使用场景,优缺点,代码示例)
  • Rust:构造函数 new() 如何进行错误处理?
  • 信号(Signal)** 是一种进程间异步通信机制,用于通知进程发生发生了某种事件(如错误、用户中断等)
  • 疯狂星期四文案网第37天运营日记
  • Apache POI中通过WorkBook写入图片后出现导出PDF文件时在不同页重复写入该图片问题,如何在通过sheet获取绘图对象清除该图片
  • 通过限制对象的内存分配位置来实现特定的设计目标
  • 【数据结构入门】堆
  • powerbi本地报表发布到web,以得到分享链接
  • C99中的变长数组(VLA)
  • 什么是 Spring MVC?
  • 中扬立库与西门子深化技术协同 共绘智能仓储创新蓝图
  • clean install 和 clean package 的区别