积木套娃
积木可以旋转,即[3,6]可以变为[6,3]
public int solve(int[][] arr){
if(arr==null||arr.length==0)return 0;
standard(arr);
//按照长度升序排列,相等宽度升序
Arrays.sort(arr,(a,b)->{
return a[0]==b[0]?a[1]-b[1]:a[0]-b[0];
});
//定义dp[i]为考虑前i个元素,以第i个积木结尾的最多积木摆法
int[] dp = new int[arr.length];
Arrays.fill(dp,1);//每个至少都可以摆自己
//如果宽度比当前的大就说明可以装的下
int res=0;
for (int i = 1; i < arr.length; i++) {
//只可能往前面取,因为后面的长都大于等于它自己
for (int j = 0; j < i; j++) {
if(arr[j][1]<=arr[i][1]){
dp[i]=Math.max(dp[i],dp[j]+1);
res=Math.max(dp[i],res);
}
}
}
return res;
}
//变化函数,标准化长和宽为[长,宽]
public void standard(int[][] arr){
for (int i = 0; i < arr.length; i++) {
if(arr[i][0]<arr[i][1]){
int temp=arr[i][0];
arr[i][0]=arr[i][1];
arr[i][1]=temp;
}
}
}
压缩字符串
//输入aaabbbccAAA 返回 [3, 2, 1, 3, 2, 1, 2, 1, 1, 1, 1]
//计算连续字符的重复次数
int[] calRepTable(String s){
int[] res = new int[s.length()];//代表从i以后包括i本身一共有多少个重复字符
res[s.length()-1]=1;
char prev=s.charAt(s.length()-1);
//记录重复串数量
int num=1;
for (int i = s.length()-2; i >=0; i--) {
//当前字符为大写字母或者不与之前的字母相等的时候,重置为1
if(s.charAt(i)!=prev||!(s.charAt(i)>='a'&&s.charAt(i)<='z')){
num=1;
}else{
num++;
}
res[i]=num;
prev=s.charAt(i);
}
return res;
}
//返回子串的重复数量 abcabcabc返回3
int getRepTimes(String s,int i,int l){
int rep=1;
while (i+l*rep+1<=s.length()){
//java的substring方法与c++不同,参数是两个索引
String s1=s.substring(i,l+i);
String s2=s.substring(i+rep*l,l+i+rep*l);
if(!s1.equals(s2))break;
++rep;
}
return rep;
}
//主方法
String zip(String string){
StringBuilder s1 = new StringBuilder();
int[] repTable = calRepTable(string);
//优先压缩最长的子串
for (int i = 0; i < string.length(); i++) {
boolean anyZip=false;
//l代表的是字符串长度,判断是否重复至少要从剩余的子串的1/2长度开始判断,然后慢慢减少长度
for (int l = (string.length()-i)/2; l >repTable[i] ; --l) {
int repTimes=getRepTimes(string,i,l);
if(repTimes>1){
//处理重复的子串
s1.append(string.substring(i,i+l).toUpperCase()+Integer.toString(repTimes));
//跳过重复的子串
i+=l*repTimes-1;
anyZip=true;
break;
}
}
//如果没有压缩的情况出现就按顺序添加
if(!anyZip){
s1.append(string.charAt(i));
}
}
StringBuilder s2 = new StringBuilder();
int[] repTable1 = calRepTable(s1.toString());//从后往前进行单字符的压缩
//处理重复的子串
for (int i = 0; i < s1.length(); i++) {
if(repTable1[i]>2){
s2.append(s1.charAt(i));
s2.append(Integer.toString(repTable1[i]));
i+=repTable1[i]-1;
}else{
s2.append(s1.charAt(i));
}
}
return s2.toString();
}
货仓问题
//数组 长度 返回一共可以得到多少货物
public int dealCargo(int[] arr, int N) {
int max = dealArr(arr);
if (max == 0) return 0;
int res=0;
//dp[i][j]表示的是对于位置[i]的平面[j]当前累加的长度
int[][] dp = new int[arr.length][max + 1];
//base
for (int i = 0; i < arr.length; i++) {
int height=arr[i];
for (int j = 1; j <=height ; j++) {
dp[i][j]=dp[i-1][j]+1;
if(dp[i][j]==N){
res++;
dp[i][j]=0;
}
}
}
return res;
}
//处理数组 并且返回最大值
public int dealArr(int[] arr) {
int max = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] < 0) {
arr[i] = -arr[i];
} else {
arr[i] = 0;
}
max = Math.max(max, arr[i]);
}
return max;
}