【JAVA】1008 数组元素循环右移问题 (20分) PAT乙级 PAT (Basic Level) Practice (中文)

前言

学得越多,不会得越多
种一颗树的最佳时间是十年前,其次就是现在

pat所有题解代码都会陆续上传到Github,请好兄弟们自行下载:https://github.com/233zzh/PAT
qq交流群:1107710098

题目:1008 数组元素循环右移问题 (20分)

题目链接:https://pintia.cn/problem-sets/994805260223102976/problems/994805316250615808

一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由``( A 0 A_0 A0 A 1 A_1 A1 A N − 1 A_{N-1} AN1)变换为( A N − M A_{N-M} ANM··· A N − 1 A_{N-1} AN1 A 0 A_0 A0 A 1 A_1 A1··· A N − M − 1 A_{N-M-1} ANM1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:
每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。

输出格式:
在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

输入样例:

6 2
1 2 3 4 5 6

输出样例:

5 6 1 2 3 4

要点:M可能大于N

解决办法:

M = M % N; //M可能大于N

代码一:暴力

import java.util.Scanner;

public class LoopArray {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int M = sc.nextInt();
        M = M % N;
        int[] arr = new int[N];

        for (int i = 0; i < N; i++) {
            arr[i] = sc.nextInt();
        }

        for (int i = 0; i < M; i++) {
            int tmp = arr[N - 1];
            for (int j = N - 1; j > 0; j--) {
                arr[j] = arr[j - 1];
            }
            arr[0] = tmp;
        }

        for (int i = 0; i < N - 1; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.print(arr[N - 1]);
    }
}

代码二:反转

三步走策略:先反转前面部分,再反转后面部分,最后再对整体进行反转。
也就是代码中的这三行(如下),关键是参数的设定,哪里该减一,哪里不能减一,(技巧就是用具体数字代入试一试)。
另外,reverse函数的编写,也是同样,难点是下标的计算,功能是原地反转。

  1. reverse(arr, 0, N - M - 1);
  2. reverse(arr, N - M, N - 1);
  3. reverse(arr, 0, N - 1);

在这里插入图片描述

import java.util.Scanner;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author: 张志浩 Zhang Zhihao
 * @Email: 3382885270@qq.com
 * @Date: 2020/11/27
 * @Time: 17:58
 * @Version: 1.0
 * @Description: Description
 */
public class ShiftRight3 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int M = sc.nextInt();
        M = M % N; //M可能大于N
        int[] arr = new int[N];
        for (int i = 0; i < N; i++) {
            int input = sc.nextInt();
            arr[i] = input;
        }
        sc.close();

        reverse(arr, 0, N - M - 1);
        reverse(arr, N - M, N - 1);
        reverse(arr, 0, N - 1);

        for (int i = 0; i < N - 1; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.print(arr[N - 1]);
    }

    private static void reverse(int[] arr, int start, int end) {
        for (int i = start; i <= (start + end) / 2; i++) {
            int temp = arr[i];
            arr[i] = arr[end + start - i];
            arr[end + start - i] = temp;
        }
    }
}


代码三:投机取巧(输入的时候使用循环队列的思想:)

一般这种代码没法用,因为一般情况下会给你传一个数组,而不是让你从控制台读取,我们这种投机其实相当于使用了一个新数组,而不是在原来数组上原地变换

import java.util.Scanner;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author: 张志浩 Zhang Zhihao
 * @Email: 3382885270@qq.com
 * @Date: 2020/11/27
 * @Time: 18:12
 * @Version: 1.0
 * @Description: Description
 */
public class ShiftRight4 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int M = sc.nextInt();
        M = M % N; //M可能大于N
        int[] arr = new int[N];
        for (int i = 0; i < N; i++) {
            int input = sc.nextInt();
            arr[(i + M) % N] = input;
        }
        sc.close();

        for (int i = 0; i < N - 1; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.print(arr[N - 1]);
    }
}

代码四:优化,减少交换次数,但是比较难

import java.util.Scanner;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author: 张志浩 Zhang Zhihao
 * @Email: 3382885270@qq.com
 * @Date: 2020/11/27
 * @Time: 15:03
 * @Version: 1.0
 * @Description: Description
 */
public class ShiftRight2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int M = sc.nextInt();
        M = M % N; //M可能大于N
        int[] arr = new int[N];
        for (int i = 0; i < N; i++) {
            int input = sc.nextInt();
            arr[i] = input;
        }
        sc.close();
        if (N % 2 == 0) {
            int flag;
            flag = M <= N / 2 ? M : N - M;
            for (int i = 0; i < flag; i++) {
                int temp = arr[i];
                int index = i;
                /*for (int k = 0; k < N / M; k++) {
                    index = (index + M) % N;
                    int temp1 = arr[index];
                    arr[index] = temp;
                    temp = temp1;
                }*/
                while (true) {
                    index = (index + M) % N;
                    int temp1 = arr[index];
                    if (temp1 == temp) {
                        break;
                    }
                    arr[index] = temp;
                    temp = temp1;
                }
            }
        } else {
            int temp = arr[0];
            int index = 0;
            for (int k = 0; k < N; k++) {
                index = (index + M) % N;
                int temp1 = arr[index];
                arr[index] = temp;
                temp = temp1;
            }
        }
        for (int i = 0; i < N - 1; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.print(arr[N - 1]);
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱做梦的鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值