題目:
給定一個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()+" "); } } }
碼字來之不易,有幫助的夥伴點個贊鴨~