蓝桥杯算法训练-数组移动

蓝桥杯算法训练题解
更好的阅读体验

题目描述

初始数组A[N]中为1,2,…,N,N个数字,现要进行M次操作,每次操作给定一个数字i,记其在数组中的位置为Bi,将A[1]…A[Bi]移到数组末尾。

题解

  • 首先,需要认清这个移动其实是一个循环右移的过程
  • 其次,要知道循环右移是可以累计的,比如第一次右移了b1位,第二次右移了b2位,那么数字x对应的下标就会变成 ( x − 1 + b 2 + b 2 ) m o d    n (x - 1 + b2 + b2) \mod n (x1+b2+b2)modn,也就是 ( x − 1 + t o t a l ) m o d    n (x - 1 + total) \mod n (x1+total)modn, total是每次右移的总和。这样就可以在 O ( 1 ) O(1) O(1)时间复杂度内求出x对应的坐标是多少了。
  • 最后,只需要知道每一次右移多少位就行了,可以发现,把 x x x所在的下标 b b b右移到 n − 1 n - 1 n1,右移了 ( n − b − 1 ) (n - b - 1) (nb1)位。
  • 补充,这里假设数组下标从0开始

代码

  • java

下面注释掉的代码是使用hash表进行处理的代码,时间复杂度 O ( n ∗ m ) O(n * m) O(nm),因为初始没有发现是循环右移操作,最后手动计算了一下才发现, 另外C++代码看着自己写吧。这么简单没有必要重写c++了。


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * @author: Zekun Fu
 * @date: 2022/10/28 17:29
 * @Description:
 */
public class Main {

//    1 2 3 4 5
//    4 5 1 2 3
//    3 4 5 1 2
//    之前的数字都加上了(n - Bi - 1);
//    之后的数字都减去了(n - Bi - 1);
//    使用ha是存储每一个数字的位置,找到这个位置,
//    遍历hash表,之前的数字都加上n - 1 - Bi,之后的数字都减去n - 1 - Bi

    public static void main(String[] args) throws Exception{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
        String[] firstLine = in.readLine().split(" ");
        int n = Integer.valueOf(firstLine[0]);
        int m = Integer.parseInt(firstLine[1]);
        HashMap<Integer, Integer> mp = new HashMap<>();
        int total = 0;              // 循环右移的位数
        for (int i = 0; i < m; i++) {
            int x = Integer.valueOf(in.readLine());
            int b = (x - 1 + total) % n;      // x所在的下标b
            total += (n - 1 - b);             // 现在右移的位数
        }
//        for (int  i = 1; i <= n; i++) mp.put(i, i - 1);
//        for (int i = 0; i < m; i++) {
//            int x = Integer.valueOf(in.readLine());
//            int b = mp.get(x);
//            for (Integer key : mp.keySet()) { // 循环右移n - i - 1位
//                int p = mp.get(key);
//                p = (p + n - 1 - b) % n;
//                mp.put(key, p);
//            }
//        }
        int[] ans = new int[n];
        for (int i = 1; i <= n; i++) {
            int p = (i - 1 + total) % n;
            ans[p] = i;
        }
        for (int x : ans) out.write(x + " ");
        out.flush();
        out.close();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值