各种转的操作

85 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情

前言:

在平时刷算法题过程中,我们经常碰到图片所示问题 image.png

虽然他们的描述和结构都各有特点,但是我觉得既然是反转就一定有相同点。

比如:你如何把12345678变成87654321?

我们很容易想到,把他用数组存储,然后对数组反向打印。这个确实是一个办法,但是万一他原本是一个long型的数字呢?或者他是char类型呢?或者是String类型呢? 那么我们把他转成数组,是不是浪费了内存呢?

String类型的反转:

在Java里面我们可以使用 StringBuffer.reverse()方法或者调用String对象的charAt()方法,将字符串从后往前依次取出来,或者将String字符串转换成字符数组,反转字符数组

  1. 字符串反转(数组)
输入: 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--;
        }
        }
  1. 字符串(调用revorce)
String reverse(String str){ 
StringBuffer sb = new StringBuffer(str);
sb.reverse();
return sb.toString();
}
  1. 字符串(调用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();
}
  1. 字符串(变成数组)
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;

像这样的代码看上去就很方便的进行了反转。基本思想是:通过取余,拿到每一位,然后进行拼接,得到反转结果

image.png

数组反转

输入一个二维数组,把他顺时针旋转90度

image.png

这个旋转看上去有点困难,但是找到规律后非常简单。1.以主对角线交换元素 2.按最中间列作为对称进行交换

image.png

那么对角线交换代码非常简单: 二重循环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来计算重新赋值的元素下标

image.png

可以进行多次反转

image.png

链表反转

image.png

链表反转使用的一种方式是栈,栈先进后出。实现原理就是把链表节点一个个入栈,当全部入栈完之后再一个个出栈,出栈的时候在把出栈的结点串成一个新的链表

首先把链表节点加入栈,然后当栈不为空,就开始出栈

image.png

唔:看上去好像没什么联系呢

其实对应数组轮转,字符串反转,数组反转这种可以直接交换的,我们可以使用如图的方式。 image.png

对于可以使用的一维数组的元素,可以使用双指针方法

image.png

看到这个双指针,我又想起来查询元素,大家也可以想想。

对于二维数组:如果进行旋转,可以优先考虑对称交换的规律。