1025 反轉鏈表 (25 分) PAT (Basic Level) Practice (中文)
給定一個常數 K 以及一個單鏈表 L,請編寫程序將 L 中每 K 個結點反轉。例如:給定 L 爲 1→2→3→4→5→6,K 爲 3,則輸出應該爲 3→2→1→6→5→4;如果 K 爲 4,則輸出應該爲 4→3→2→1→5→6,即最後不到 K 個元素不反轉。
輸入格式:
每個輸入包含 1 個測試用例。每個測試用例第 1 行給出第 1 個結點的地址、結點總個數正整數 N (≤105)、以及正整數 K (≤N),即要求反轉的子鏈結點的個數。結點的地址是 5 位非負整數,NULL 地址用 −1 表示。
接下來有 N 行,每行格式爲:
Address Data Next
其中 Address
是結點地址,Data
是該結點保存的整數數據,Next
是下一結點的地址。
輸出格式:
對每個測試用例,順序輸出反轉後的鏈表,其上每個結點佔一行,格式與輸入相同。
輸入樣例:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
輸出樣例:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
作者: CHEN, Yue
單位: 浙江大學
時間限制: 400 ms
內存限制: 64 MB
代碼長度限制: 16 KB
分析:
- 輸入的節點信息,並不是按鏈表順序輸入的。這意味着必須將輸入信息存起來。
- 有可能存在“虛假節點”,即該節點並不在實際所求的鏈表上。
- 由於題目沒有交代若該鏈表是空鏈表時如何輸出,可以認爲鏈表至少有一個節點。
- 每湊夠K個節點來一輪逆置,但最後若湊不夠K個則不逆置!所以要預判數量。
- 注意輸出的地址要湊足5位數,除了-1外。
解題思路:
- 直接映射哈希法存儲節點:由分析1,且有效地址是不超過5位數的非負整數,用長度爲100000的數組A[]存儲節點。
- 用順序表模擬鏈表:用數組link[]按鏈表的順序存儲輸入所代表的鏈表,但只存儲<address,data>,因爲可以用下標遍歷而不需要next。(反正都用了哈希存儲,空間複雜度不可能<O(N)了)
- 在順序表(link[])中完成逆置:每湊夠K個節點來一輪逆置,逆置操作用雙指針迭代交換完成,最後不足K個節點跳出。
- 將link[]模擬的鏈表打印出來:注意鏈表長度不一定爲N,要以實際記錄的長度爲準,可以在link[]末端插入地址-1作爲哨兵。
Python3版本:(有超時)
因爲最近在學Python,所以一開始就上手Python代碼,如下:
#1025 反轉鏈表 (25 分)
link=[None]*100000 #add最大99999
head,N,K=map(int,input().split(' '))
for i in range(N):
add,data,next=map(int,input().split(' '))
link[add]=[data,next]
T,p=[],head
while -1!=p:
if None==link[p]:break
#print(p,*node)
T.append(["%05d"%(p) ,link[p][0]])
p=link[p][1]
for j in range(K-1,len(T),K):
i=j-K+1
while i<j:
T[i],T[j]=T[j],T[i]
i+=1
j-=1
T.append(['-1'])
for i in range(len(T)-1):
print("%s %d %s"%(T[i][0],T[i][1],T[i+1][0]))
Python的優點是代碼簡潔,但因爲其是解釋型程序,當代碼有大量循環語句和輸入輸出時,那就坑了。如果有大佬能用Python版本AC的,請賜教。
C++版本(AC)
和上面的Python解法完全一樣,只因爲輸入輸出快了,所以能AC。
//1025 反轉鏈表 (25 分)
#include <stdio.h>
#include<map>
using namespace std;
pair<int, int> A[100000]; //0~99999 A[]=<data,next>
int main(){
int head, N, K;
scanf("%d %d %d", &head, &N, &K);
pair<int, int> *link = new pair<int, int>[N+1]; //用順序表模擬鏈表
while (N-- > 0) {
int p, data, next;
scanf("%d %d %d", &p, &data, &next);
A[p] = { data,next }; //直接映射哈希存儲:p爲關鍵詞
}
int len = 0; //link數組(代表鏈表)的有效長度
while (-1 != head) {
link[len++] = { head,A[head].first }; //={add,data}
head = A[head].second; //=next
}
for (int step = K; step <= len; step+=K) { //每湊足K個逆置
for (int i = step - K, j = step - 1; i < j; i++, j--) {
swap(link[i], link[j]); //交換
}
}
for (int i = 0; true; ) {
printf("%05d %d ", link[i].first, link[i].second);
if (++i<len)
printf("%05d\n", link[i].first);
else{ //是最後一個
printf("-1\n"); break;
}
}
return 0;
}
其實沒比Python版本長多少,所以此題不適合用Python。