当前位置: 首页 > 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.lryc.cn/news/618905.html

相关文章:

  • 牛客疑难题(6)
  • Transformer的编码器与解码器模块深度解析及python实现完整案例
  • 树:数据结构中的层次架构
  • 前端基础知识NodeJS系列 - 06( Node 中的 Stream 的理解?应用场景?)
  • 【154页PPT】某大型再生资源集团管控企业数字化转型SAP解决方案(附下载方式)
  • 【从零开始java学习|第三篇】变量与数据类型的关联
  • 扣子空间深度解析
  • Apache 服务器基础配置与虚拟主机部署
  • CentOS 7.9 升级 GLibc 2.34
  • (C++)继承全解析及运用
  • Java 大视界 -- Java 大数据在智能教育学习效果评估指标体系构建与精准评估中的应用(394)
  • 教程 | 用Parasoft SOAtest实现高效CI回归测试
  • Day02——Docker
  • 一体化步进伺服电机在无人机舱门应用中的应用案例
  • 书籍数组中未出现的最小正整数(8)0812
  • 小白挑战一周上架元服务——ArkUI04
  • Ubuntu与Rocky系统安装Java全指南
  • C# 基于halcon的视觉工作流-章29-边缘提取-亚像素
  • 深入理解数据库架构:从原理到实践的完整指南
  • 力扣47:全排列Ⅱ
  • ffmpeg,ffplay, vlc,rtsp-simple-server,推拉流命令使用方法,及测试(二)
  • Linux内核编译ARM架构 linux-6.16
  • 深度贴:前端网络基础及进阶(3)
  • archlinux中VLC无法播放视频的解决办法
  • Linux TC流控实现机制
  • MySQL——MySQL引擎层BufferPool工作过程原理
  • leetcode3258:统计满足K约束的子字符串数量Ⅰ(变长滑动窗口详解)
  • Tricentis Tosca 2025.1 LTS 系统要求
  • Java 中 Set 接口详解:知识点与注意事项
  • Day50--图论--98. 所有可达路径(卡码网),797. 所有可能的路径