360 || 2021校園招聘的一道筆試題思路分享

題目:
給定一個1到N的排列P1到PN(N爲偶數),初始時Pi=i(1≤i≤N),如今要對排列進行M次操做,每次操做爲如下兩種中一種:
①將排列的第1個數移到末尾;
②交換排列的第1個數與第2個數、第3個數與第4個數、…、第N-1個數與第N個數。
求通過這M次操做後獲得的排列。



java

輸入描述
第一行包含兩個整數N和M,2≤N,M≤10^5。
第二行包含M個空格隔開的整數t1到tM,1≤ti≤2。若ti=1,則表示第i次操做爲操做①;若ti=2,則表示第i次操做爲操做②。
輸出描述
輸出N個空格隔開的整數,即通過M次操做後獲得的排列。
示例
輸入:
6 3
1 2 1
輸出:
2 5 4 1 6 3
描述:
一開始是 1 2 3 4 5 6,通過操做1後爲:2 3 4 5 6 1,通過操做2後爲:3 2 5 4 1 6,通過操做1後爲:2 5 4 1 6 3











數組

思路 基於java

首先這道題,即便你啥都不會,你也能夠經過暴力法解決,咱們可使用一個LinkedList,當操做1時,pollfirst而後將其add到尾部;操做2時,就交換。
可是當數據量變大或者操做變得頻繁,問題就來了,很明顯最耗時間的是操做2,這個時間複雜度的O(n/2*(操做2的次數))。
spa

那咱們能不能想辦法把操做2聚合起來?
固然是能夠,可是有一個問題,中間有若干次操做1怎麼辦?
那好,我遇到操做1我就把目前操做2的聚合執行一次。
那若是我是2,1,2,1,2,1....怎麼辦?


code

讓咱們再來分析下示例,操做1 2 1變化過程爲:
1 2 3 4 5 6
2 3 4 5 6 1 ···· 操做1
3 2 5 4 1 6 ···· 操做2
2 5 4 1 6 3 ···· 操做1



blog

操做1的步驟,實際上就是一次更換鏈表頭」的操做,鏈表頭變成了下一個元素;
操做2的步驟,實際上也是一次更換鏈表頭」的操做(對於表頭而言),鏈表頭變成了下一個元素;
圖片

二者對於鏈表表頭來講,其實都包含了一次更換鏈表頭爲原鏈表頭下一元素的操做。get

再來講操做2,操做2是交換排列的第1個數與第2個數、第3個數與第4個數、…、第N-1個數與第N個數。發現了嗎,這個操做很單一呀,都只是前一個跟後一個交換位置。ast

咱們爲何用鏈表來作呢?由於操做1的關係,註定咱們用數組來作是不友好的。那由這裏引伸,咱們是否是有必要維持整個數據在同一條鏈表裏面?class

仔細看看操做1,由於題目說鏈表的長度是偶數(咱們這裏的座標看成是1開始好了,比較容易理解),其實也就是把表頭(奇數位置)放到一個偶數位置後面而已;
操做2,不過就是把奇偶數的位置互換而已。
變量

來個圖吧!
在這裏插入圖片描述
發現了嗎,操做一、2好像每次都會更換紅藍色數據的位置。咱們能夠維持兩個鏈表,一個奇數一個偶數。而正確結果,是先打印上面的一個數據,而後再下面的一個數據,上下上下…因此咱們須要一個變量來標識,當前應該先從奇數鏈表開始,仍是先從偶數鏈表開始。

上上代碼,或許你該差很少懂了。

public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            int n = scanner.nextInt();
            int m = scanner.nextInt();
            int[] arr = new int[m];
            for (int i = 0; i < m ; i++) {
                arr[i] = scanner.nextInt();
            }
            getOut(n,arr);
        }
    }

    private static void getOut(int n, int[] arr) {
        if(arr.length>100000){
            return;
        }
        LinkedList<Integer> list1 = new LinkedList<>();
        LinkedList<Integer> list2 = new LinkedList<>();
        boolean flag = true; // true的時候把list1當成首 false時list2爲首
        for (int i = 1; i <= n ; i++) {
            if (i%2!=0){
                list1.add(i);
            }else {
                list2.add(i);
            }
        }
        for (int i = 0; i < arr.length ; i++) {
            if (arr[i]==1){
                if (flag){
                    Integer val = list1.pollFirst();
                    list1.addLast(val);
                }else {
                    Integer val = list2.pollFirst();
                    list2.addLast(val);
                }
                flag = !flag;
            }else if (arr[i]==2){
                flag = !flag;
            }
        }
        if (flag){
            while (!list1.isEmpty()&&!list2.isEmpty()){
                System.out.print(list1.pollFirst()+" ");
                System.out.print(list2.pollFirst()+" ");
            }
        }else {
            while (!list1.isEmpty()&&!list2.isEmpty()){
                System.out.print(list2.pollFirst()+" ");
                System.out.print(list1.pollFirst()+" ");
            }
        }
    }

碼字來之不易,有幫助的夥伴點個贊鴨~

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息