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;
    }
}
相关文章
|
机器学习/深度学习 人工智能
|
机器学习/深度学习
Dp练习
Dp练习
80 0
9.DP单调队列优化
先弄出朴素DP->在用单调队列优化 一般都是区间的最大最小值,而且滑动的,才用单调队列优化
53 0
|
定位技术
DFS:踏青
DFS:踏青
|
算法 BI
数位统计DP
复习acwing算法基础课的内容,本篇为讲解基础算法:动态规划——数位统计DP,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。
107 0
数位统计DP
|
算法
迭代加深(DFS)
复习acwing算法提高课的内容,本篇为讲解算法:迭代加深,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。
140 0
迭代加深(DFS)
dfs
题目描述 你有一张某海域NxN像素的照片,"."表示海洋、"#"表示陆地,如下所示: ....... .##.... .##.... ....##. ..####. ...###. ....... 其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。 由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。 例如上图中的海域未来会变成如下样子: ....... ....... ....... ....... ....#.. ......
【LeetCode494】目标和(暴搜dfs或dp)
1 <= nums.length <= 20 0 <= nums[i] <= 1000
99 0
【LeetCode494】目标和(暴搜dfs或dp)
计蒜客-1217 马走日(dfs)
马在中国象棋以日字形规则移动。
210 0