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] | 10 | 9 | 2 | 5 | 3 | 7 | 101 | 18 |
dp[i] | 1 | 1 | 1 | 2 | 2 | 3 | 4 | 4 |
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));
}
}