DFS,DP

简介: DFS,DP

力扣526.优美的排列

class Solution {
    int count=0;
    boolean vis[];
    public int countArrangement(int n) {
        vis=new boolean[n+1];
        //我的问题1:不知道参数设置什么,有些遗忘,参数要去设置下标排到什么位置
     dfs(1,n);
     return count;
    }
    //实现
    public void dfs(int pos,int n){
   if(pos==n+1){
    count++;
    return ;
   }
   for(int i=1;i<=n;i++){
    if(vis[i]==false&&(i%pos==0||pos%i==0)){
        vis[i]=true;
        dfs(pos+1,n);
        vis[i]=false; //恢复现场
    }
    }
   }
}

力扣1027.最长等差数列

dp:以i位置的元素为结尾的所有子序列中,最长的等差序列长度

dp[i-1],dp[i-2],....dp[0]——dp[i],因为只存了一个长度,但是我们只是知道长度,我们连最基础的等差序列长什么样子都不清楚。.

状态表示一定要包含两个信息:1.长度2.等差序列的样子

dp[i][j]:i位置以及j位置为结尾的所有子序列中,最长的等差序列的长度。(i<j)

初始化:

dp表里面,所有的值,都初始化为2

(提问:假如dp[0][0]那么不就是一个元素,那么不就是1吗,

答:i<j.  我们只会用到对角线的上半部分,连对角线都用不到,所以直接全初始化

4.填表顺序

1.先固定最后一个数,2.枚举倒数第二个数

或者

1.先固定倒数第二个数,2.枚举倒数第一个数。

class Solution {
    public int longestArithSeqLength(int[] nums) {
   //建标,为什么使用Map,因为假如要找那个距离i最近的下标,还需要一层遍历,这样很大概率超时,所以使用MAP来去存储距离最近的i那个下标
   //一遍dp,一边保存距离他最近的下标
   Map<Integer,Integer>hash=new HashMap<Integer,Integer>();
   //a的位置可能有nums[0]
   hash.put(nums[0],0);
   int n=nums.length;
   int [][]dp=new int[n][n];
   //我们只会用到dp的上半部分,因为i<j的
   for(int i=0;i<n;i++){    //初始化
    Arrays.fill(dp[i],2);
   }
   int ret=2;
   //i从0开始,j从1开始,那么dp表初始化的值本来就是2,没有意义,他不可能是3
  // ,所以需要i从1开始,j从2开始
 
  //固定了i位置,接下来枚举即可
   for(int i=1;i<n;i++){
    //j在i的后面,他本质还是一维数组
    for(int j=i+1;j<n;j++){
        //本质还是看一维数组  i :a j:b 以ij结尾
       // a-x=b-a,所以x=2a-b;
        int a=2*nums[i]-nums[j];
        //看a是否存在
        if(hash.containsKey(a)){
            //get(a),获取a元素所在的下标
            dp[i][j]=dp[hash.get(a)][i]+1;
            ret=Math.max(ret,dp[i][j]);
        }
    }
    //说明i走完了,把i位置扔进哈希表里面
    hash.put(nums[i],i);
   }
return ret;
 
 
    }
}

力扣300.最长递增子序列

子序列:[a,b,c,d,e]按从左往右的顺序,任意挑选几个,[a,b,d]相对的顺序不变。

子数组:子数组,必须跳出来后是连续的

子序列>子数组

class Solution {
    public int lengthOfLIS(int[] nums) {
//dp[i]以i位置为结尾的子序列,最长子序列的长度
//状态表示分为两大类
//1.自己玩,长度为1
//2.跟在前面元素后面,构成递增子序列,nums[j]<nums[i]
   int max1=1; 
   int n=nums.length;
     int []dp=new int[n];
   Arrays.fill(dp,1);
   //从左往右
 
   for(int i=1;i<n;i++){
    for(int j=0;j<i;j++){
   if(nums[j]<nums[i]){
   //  j在 0 - i-1区间内动,为什么取一个最大值呢,因为j这个位置可以在i的前面也可以在后面,换句话说
                              //并不是一定在i-1这个位置,那么也就是说我们需要的是保存最大的dp[j],而不是最近的,推荐是去调试一下。
    dp[i]=Math.max(dp[j]+1,dp[i]);
    max1=Math.max(max1,dp[i]);
   }
    }
   }
return max1;
    }
}

力扣376.摆动序列

dp[i]:以i位置元素为结尾的所有子序列中,最长的摆动序列的长度,细分

f[i]:以i位置元素为结尾的所有子序列中,最后一个位置呈现"上升"趋势的最长摆动序列的长度

g[i]:以i位置元素结尾的所有子序列中,最后一个位置呈现"下降"趋势的最长摆动序列的长度

2.状态转移方程

f[i]:g[i-1]+1,f[i];                      

g[i]:f[i-1]+1,g[i];

初始化

全部是1呗

i位置结尾的最大值 他那个遍历max意味着

他从前面一堆中 找出最长的和这个看能不能连上,如果能连上且最长那么就+1 ,假如说他这个值不是最长 那么她就保留原有的i位置和j位置连起来的那个最长

max的意思是说 前面那个有可能连上 但是不一定最长

(虽然f[i]:g[i-1]+1,f[i];  这里你写一个f[i-1]也是对的,但是这样他就不是正确的含义了,假如你当前呈现上升趋势,然后f[i-1]是以i-1位置结尾的最大上升趋势,这样换句话说,就会i越大,f越大,g也一样,那么最后迎来的就是f[n-1]和g[n-1]求max值,来计算了 )

class Solution {
    public int wiggleMaxLength(int[] nums) {
        int n=nums.length;
        //f[i]:以i位置元素为结尾的所有子序列中,最后一个位置呈现"上升"趋势的最长摆动序列的长度
//g[i]:以i位置元素结尾的所有子序列中,最后一个位置呈现"下降"趋势的最长摆动序列的长度
    int []f=new int[n];
    int []g=new int[n];
    Arrays.fill(f,1);
    Arrays.fill(g,1);
    //dp[i]:表示以i位置元素为结尾的所有子序列,最长的摆动序列长度。
    int ret=1;
    for(int i=1;i<n;i++){
        for(int j=0;j<i;j++){//j在i的前面
         if(nums[j]<nums[i]){
        f[i]=Math.max(f[i],g[j]+1);}
      else  if(nums[j]>nums[i]){
        g[i]=Math.max(g[i],f[j]+1);
    }
        }
    ret=Math.max(ret,Math.max(f[i],g[i]));
        }
return ret;
    }
}
目录
打赏
0
0
0
0
27
分享
相关文章
深入理解Java中的并发编程
【4月更文挑战第24天】 在本文中,我们将探讨Java并发编程的核心概念,包括线程、锁、同步和并发集合。我们将深入了解这些概念如何帮助开发人员编写高效且线程安全的代码。我们还将讨论一些常见的并发问题,如死锁和竞态条件,并探讨如何使用Java的并发工具来解决这些问题。最后,我们将通过一些示例来展示如何使用Java的并发特性来提高程序的性能和可扩展性。
【Python百日刷题计划】熟练使用几个重要的内置函数
【Python百日刷题计划】熟练使用几个重要的内置函数
220 0
kde
|
15天前
|
Docker镜像加速指南:手把手教你配置国内镜像源
配置国内镜像源可大幅提升 Docker 拉取速度,解决访问 Docker Hub 缓慢问题。本文详解 Linux、Docker Desktop 配置方法,并提供测速对比与常见问题解答,附最新可用镜像源列表,助力高效开发部署。
kde
9382 76
|
12天前
typora免费版,激活方法,Typora使用教程
Typora是一款简洁高效的Markdown编辑器,支持即时渲染。本教程涵盖安装方法、文件操作、视图控制、格式排版、字体样式及Markdown语法,助你快速上手使用Typora进行高效写作。
2390 6
Dify MCP 保姆级教程来了!
大语言模型,例如 DeepSeek,如果不能联网、不能操作外部工具,只能是聊天机器人。除了聊天没什么可做的。
2252 34
Windows安装Claude Code
Claude Code 是 Anthropic 推出的代码助手,支持在 Windows 通过 WSL(Windows Subsystem for Linux)运行。本文介绍如何在 Windows 系统中启用 WSL、安装 Ubuntu 子系统、配置 Python 与 Node.js 环境,并最终安装和运行 Claude Code。内容涵盖 WSL 设置、开发工具安装、依赖配置及常见问题解决方法,助你顺利在本地环境中使用 Claude Code 提升编码效率。
595 1
Windows安装Claude Code
AI助理

你好,我是AI助理

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