开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
前言:
在平时刷算法题过程中,我们经常碰到图片所示问题
虽然他们的描述和结构都各有特点,但是我觉得既然是反转就一定有相同点。
比如:你如何把12345678变成87654321?
我们很容易想到,把他用数组存储,然后对数组反向打印。这个确实是一个办法,但是万一他原本是一个long型的数字呢?或者他是char类型呢?或者是String类型呢? 那么我们把他转成数组,是不是浪费了内存呢?
String类型的反转:
在Java里面我们可以使用 StringBuffer.reverse()方法或者调用String对象的charAt()方法,将字符串从后往前依次取出来,或者将String字符串转换成字符数组,反转字符数组
- 字符串反转(数组)
输入: s = ["h","e","l","l","o"]
输出: ["o","l","l","e","h"]
- 直接法:直接循环前半部分,然后把前半部分后后半部分依次交换
public void reverseString(char[] s) {
int length = s.length;
char temp;
for(int i=0;i<length/2;i++){
temp=s[i];
s[i]=s[length-1-i];
s[length-1-i]=temp;
}
}
- 双指针:一个指第一位,一个最后一位,两个进行交互后,分别向中间移动
public void reverseString(char[] s) {
int left=0;
int right=s.length-1;
while(left<right){
char tmp=s[left];
s[left]=s[right];
s[right]=tmp;
left++;
right--;
}
}
- 字符串(调用revorce)
String reverse(String str){
StringBuffer sb = new StringBuffer(str);
sb.reverse();
return sb.toString();
}
- 字符串(调用charAt)
String reverse1(String str){
StringBuilder sb = new StringBuilder();
for(int i = str.length() - 1; i >= 0; i-- ){
sb.append(str.charAt(i));
}
return sb.toString();
}
- 字符串(变成数组)
private String reverse3(String str){
char[] chars = str.toCharArray();
for (int x = 0, y = chars.length - 1; x < y; x++, y--) {
char temp = chars[x];
chars[x] = chars[y];
chars[y] = temp;
}
return new String(chars);
}
long类型数字反转:
需要取出每一位数,然后进行重新排列。
如何取出每一位数?
跳过循环,做取余操作。 一般想法:int yushu=x%10;int shiwei=x/10%10。这看来代码很冗余。
public int reverse(long x) {
long res = 0;
while (x != 0) {
res = res * 10 + x % 10;//res*10+个位
x /= 10;//前n-1位
}
return (int) res == res ? (int) res : 0;
像这样的代码看上去就很方便的进行了反转。基本思想是:通过取余,拿到每一位,然后进行拼接,得到反转结果
数组反转
输入一个二维数组,把他顺时针旋转90度
这个旋转看上去有点困难,但是找到规律后非常简单。1.以主对角线交换元素 2.按最中间列作为对称进行交换
那么对角线交换代码非常简单: 二重循环matrix[i][j] 和 matrix[j][i]交换。
左右代码交换:关键(循环一半长度) matrix[i] 和 matrix[length - i - 1];
数组旋转
将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
可以使用一个临时数组,先把原数组的值存放到一个临时数组中,然后再把临时数组的值重新赋给原数组,重新赋值的时候要保证每个元素都要往后移k位,如果超过数组的长度就从头开始,所以这里可以使用(i + k) % length来计算重新赋值的元素下标
可以进行多次反转
链表反转
链表反转使用的一种方式是栈,栈先进后出。实现原理就是把链表节点一个个入栈,当全部入栈完之后再一个个出栈,出栈的时候在把出栈的结点串成一个新的链表。
首先把链表节点加入栈,然后当栈不为空,就开始出栈
唔:看上去好像没什么联系呢
其实对应数组轮转,字符串反转,数组反转这种可以直接交换的,我们可以使用如图的方式。
对于可以使用的一维数组的元素,可以使用双指针方法
看到这个双指针,我又想起来查询元素,大家也可以想想。
对于二维数组:如果进行旋转,可以优先考虑对称交换的规律。