57.剪绳子
题目:
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
题解:
-
当绳子长度为2时,由于m>1,因此剪成1和1,返回1;
-
当绳子长度为3时,剪成2和1,返回2;
-
当绳子长度为4时,剪成2和2,返回4;
-
当绳子长度大于4时,将其尽可能多的剪成3,剩下的不剪即可。
public int cuttingRope(int n) {
if(n == 2)return 1;
if(n == 3)return 2;
if(n == 4)return 4;
int res = 1;
while(n > 4){
res *= 3;
n -= 3;
}
return res*n;
}
58.和为s的连续正数序列
题目:
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
题解:
- 由于是连续正整数序列且至少包含两个数,因此初始化i = 1,j = 2,sum = 3;
- 使用双指针i 和 j 进行遍历
- 遍历结束的条件
- i == j,二者指向同一个数字不符合题目至少含有两个数,循环结束;
- 假如i == j 时未跳出循环,以target = 9为例,二者会相继一前一后的向后移动直至二者均指向9,此时返回的res中会多出不符合条件的数组[9];
- 如果
sum == target
,则将其转换为int[]类型的array,存入list; - 如果
sum >= target
,先令sum减去i,然后执行i++,使得继续向前遍历; - 如果
sum < target
,先令j++,再执行sum加上 j,继续向前遍历。
- 遍历结束的条件
public int[][] findContinuousSequence(int target) {
List<int[]> res = new ArrayList<>();
int i = 1, j = 2, sum = 3;
while (i < j){
if (sum == target){
int[] array = new int[j - i + 1];
int temp = i;
for (int s = 0; s < array.length; s++){
array[s] = temp;
temp++;
}
res.add(array);
}
if (sum >= target){
sum -= i;
i++;
}
else {
j++;
sum += j;
}
}
return res.toArray(new int[0][]);
}
- 其中
sum ==target
部分可优化为
if(s == target) {
int[] ans = new int[j - i + 1];
for(int k = i; k <= j; k++)
ans[k - i] = k;
res.add(ans);
}
59.圆圈中最后剩下的数字
题目:
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
题解:
- 将 n 个数字存入list集合;
- 通过取余操作获得每次需要删除的元素下标;
- 返回list的第一个元素即可。
public int lastRemaining(int n, int m) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < n; i++){
list.add(i);
}
int index = (m - 1) % list.size();
while (list.size() > 1){
list.remove(index);
index = (index + m - 1) % list.size();
}
return list.get(0);
}
青年孤愤,中年清高,晚年固执,一事无成