剑指 Offer 14- I. 剪绳子
题目:
给你一根长度为 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。
题解:
1.当绳子长度为2时,由于m>1,因此剪成1和1,返回1;
2.当绳子长度为3时,剪成2和1,返回2;
3.当绳子长度为4时,剪成2和2,返回4;
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;
}
剑指 Offer 62. 圆圈中最后剩下的数字
题目:
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
题解:
1.将数据存储在list集合中,并将上一次删除元素的下标记作index;
2.通过查找规律发现 index=(index+m-1)%list.size()
;
3.循环执行remove操作,直到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);
}
剑指 Offer 29. 顺时针打印矩阵
题目:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
题解:
1.定义变量:
direction
:其中0代表向右,1代表向下,2代表向左,3代表向上;a、b
:(a,b)作为当前位置,并初始化为(0,0)
2.方向的改变:
- 假如此时前进方向为右,若此时已经到达最右侧或者右边的位置已经被访问则此时需要改变方向,由向右改为向下;
- 假如此时前进方向为下,若此时已经到达最下侧或者下边的位置已经被访问则此时需要改变方向,由向下改为向左;
- …同理
3.位置的改变:
- 如果方向向右,则执行b++;
- 如果方向向下,则执行a++;
- 如果方向向左,则执行b- -;
- 如果方向向上,则执行a- -;
public int[] spiralOrder(int[][] matrix) {
if (matrix.length==0){
return new int[0];
}
// //定义前进方向direction:其中0代表向右,1代表向下,2代表向左,3代表向上
int direction = 0;//初始位置为(0,0),初始方向为右
int quantity = matrix.length*matrix[0].length;
int[] res = new int[quantity];//返回的输出数组
int a = 0,b = 0;//定义初始的横纵坐标
for (int i=0;i<quantity;i++){
res[i] = matrix[a][b];
matrix[a][b]=Integer.MAX_VALUE;//将其定义为最大值,代表已经被访问
//如果方向向右,当此时已经到达边界或者右侧已经被访问过
if (direction==0&&(b==matrix[0].length-1||matrix[a][b+1]==Integer.MAX_VALUE)){
direction=1;
}else if (direction==1&&(a==matrix.length-1||matrix[a+1][b]==Integer.MAX_VALUE)){
direction=2;
}else if (direction==2&&(b==0||matrix[a][b-1]==Integer.MAX_VALUE)){
direction=3;
}else if (direction==3&&(a==0||matrix[a-1][b]==Integer.MAX_VALUE)){
direction=0;
}
if (direction==0){
b++;
}else if (direction==1){
a++;
}else if (direction==2){
b--;
}else if (direction==3){
a--;
}
}
return res;
}
剑指 Offer 31. 栈的压入、弹出序列
题目:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
题解:
1.借助辅助栈stack
:
- 首先将
pushed[0]
压栈; - 判断此时栈顶元素是否和
poped
的元素值是否相等,若相等则进行弹栈操作,反之继续压栈 - 注意: 在不断的进行弹栈的过程中,一定记得判断此时栈是否为空,只有在不为空的前提下才可以执行
stack.peek()
操作
2.如果最后栈为空,则返回true。
public boolean validateStackSequences(int[] pushed, int[] popped) {
Stack<Integer> stack = new Stack<>();
int j=0;//记录poped下标
for (int i=0;i<pushed.length;i++){
stack.push(pushed[i]);
//注意判断栈不为空才可以执行stack.ppek()语句
while (!stack.isEmpty()&&stack.peek()==popped[j]){
stack.pop();
j++;
}
}
if(stack.isEmpty()){
return true;
}else return false;
}
听说神不能无处不在,所以创造了妈妈