T1 14- I. 剪绳子
方1:动态规划
初始条件 | dp[n] = n 1<=n<3 |
---|---|
动态方程 | dp(n) = max(dp(i)*dp(n-i)) 0<i<n |
class Solution {
public int cuttingRope(int n) {
//递归终止的条件
if(n<4){
return n-1;
}
int[] dp = new int[n+1]; //用于存放每段长度的最大成绩
//递归终止的条件
int max = 0;
for(int i=4;i<=n;i++){
max=0;
for(int j=1;j<=i/2;j++){
max = Math.max(max,dp[j]*dp[i-j]);
}
dp[i] = max;
}
return dp[n];
}
}
结论:① 当所有绳段长度相等时,乘积最大。② 最优的绳段长度为 3
x
a
=
x
n
x
=
(
x
1
x
)
n
x^a = x^\frac{n}{x}=(x^\frac{1}{x})^n
xa=xxn=(xx1)n
最优是长度为3:最优拆解 n=3a+b(a是3的除数,b是3的余数)
b=0,1,2
b=0 | n=3a |
---|---|
b=1 | //当n=10 = 3+3+3+1 或 3+3+4 //33*1=27 32*4 = 36 n=3a-1*4 |
b=2 | //11 = 3+3+3+2 或5+3+3 //33*2=54 32*5 = 45 n=3a*2 |
class Solution {
public int cuttingRope(int n) {
if(n<4) return n-1;
int a=n/3,b=n%3;
if(b==0) return (int) Math.pow(3,a); //是3的倍数
if(b==1) return (int) Math.pow(3,a-1)*4; //余1 n=4+3*(a-1)
else return (int)Math.pow(3,a) * 2;
}
}
T2 57 - II. 和为s的连续正数序列
方一:求和公式 K神题解
方二:滑动窗口(双指针)
class Solution {
public int[][] findContinuousSequence(int target) {
//i左边界 j右变界 s从i加到j (1,2,3,4.....,最大到target)
int i=1,j=2,s=3;
List<int[]> resList = new ArrayList<int[]>(); //动态修改的数组,同时保证按照首数字大小排列
while(i<j){ //左边界大于右边界
if(s==target){ //元素和等于目标,i到j存入数组
int[] num = new int[j-i+1];
for(int k=i;k<=j;k++){
num[k-i] = k ;
}
resList.add((num));
}
//相等或者元素和大于target左边界向右移
//元素和向减去要改变值 ,左边界再改变
if(s >= target){
s -= i;
i++; //向右移动左边界
}else{
//左边界向改变,元素和向再更新
j++; //向右移动右边界
s += j;
}
}
//toArray() 方法将 Arraylist 对象转换为数组
return resList.toArray(new int[0][]);
}
}
T3 62. 圆圈中最后剩下的数字
约瑟夫环
蓝色数字方便理解补充的(构建环形),红色是删除的数字
n=5,m=3
数组 0,1,2,3,4
0 | 1 | 2 | 3 | 4 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|---|---|---|---|
3 | 4 | 0 | 1 | 3 | 4 | 0 | 1 | ||
1 | 3 | 4 | 1 | 3 | 4 | ||||
1 | 3 | 1 1 | 3 | ||||||
3 |
(当前index + m) % 上一轮剩余数字的个数
class Solution {
public int lastRemaining(int n, int m) {
int x=0;
for(int i=2;i<=n;i++){
x = (x+m)%i;
}
return x;
}
}