Day76(动态规划——子序列问题)

300、最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

 dp[i]:表示以nums[i]结尾的最长子序列长度。——子序列的思维

位置i的最长升序子序列等于从0到i-1各个位置的最长升序子序列 + 1 的最大值。

例如:num[3]=5,那么索引为0~2的数组元素,判断谁比5小。可知2比5小,那么就判断dp[3]和dp[2]+1哪个大。

nums[i]109253710118
dp[i]11122344

class Solution {
    public int lengthOfLIS(int[] nums) {
        int[]dp=new int[nums.length+1];//dp[i]:表示以nums[i]结尾的最长子序列长度。
        int res=1;//因为子序列最低是1
        Arrays.fill(dp,1);//初始化dp
        for(int i=1;i<nums.length;i++){
            for(int j=0;j<i;j++){
                if(nums[i]>nums[j]){
                    dp[i]=Math.max(dp[i],dp[j]+1);
                }
            }
            res=Math.max(res,dp[i]);//求出dp数组中最大的值,就是最长子序列
        }
        return res;
    }
}

357、统计各位数字都不同的数字个数 

给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 10^n 。 

dp[3]的结果中有包含dp[2]的结果,所以想到动态规划。

推导公式—思维

以f(3)为例,在n取3的时候,三位数在数位不重复的情况下有:9x9x8种,最高位不可取0,所以1到9共9种,第二位是可以取0的,0到9共10种,但是不能与最高位重复,所以10-1得只能取9种,第三位不能与前两位重复,可取的是10-2=8种。三位数的判断完毕了。再加上dp[2],就是答案。

即:递归公式如下:

 f(3)中的9*9*8-------------->(dp[i-1]-dp[i-2])*(10-(i-1))

class Solution {
    public int countNumbersWithUniqueDigits(int n) {
        if(n==0) return 1;
        int []dp=new int[n+1];//dp[i]:表示在0~10^i之内,有多少个不同的数字
        dp[0]=1;
        dp[1]=10;
        for(int i=2;i<=n;i++){
            dp[i]=dp[i-1]+(10-(i-1))*(dp[i-1]-dp[i-2]);
        }
        return dp[n];


    }
}

 2231、按奇偶性交换后的最大数字

给你一个正整数 num 。你可以交换 num奇偶性 相同的任意两位数字(即,都是奇数或者偶数)。

 第一次看错题了,以为是奇偶索引

class Solution {
    public int largestInteger(int num) {
        //暴力
        //每次找到的数字若为偶数,则向后遍历,寻找更大的偶数,若存在,则交换位置,否则不做处理
        //每次找到的数字若为奇数,则向后遍历,寻找更大的奇数,若存在,则交换位置,否则不做处理

        String ans=String.valueOf(num);
        char[]c=ans.toCharArray();

        for(int i=0;i<c.length;i++){
            for(int j=i+1;j<c.length;j++){
                if((c[i]-'0')%2==0&&(c[j]-'0')%2==0&&(c[j]-'0')>(c[i]-'0')){
                    char temp=c[i];
                    c[i]=c[j];
                    c[j]=temp;
                }else if((c[i]-'0')%2!=0&&(c[j]-'0')%2!=0&&(c[j]-'0')>(c[i]-'0')){
                    char temp=c[i];
                    c[i]=c[j];
                    c[j]=temp;
                }
            }
        }
        return Integer.parseInt(new String(c));

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值