傳送門
https://pintia.cn/problem-sets/994805260223102976/problems/994805296180871168
題目
給定一個常數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
分析
主要是用數組來模擬鏈表的實現:
方法1(有一測試點超時):首先先將數據存入三個數組中(address數組,data數組,next數組),然后按照地址首尾相接,有序放進第四個數組中,然后對第四個數組元素按照每k個數一反轉,接著,從頭遍歷數組,將next的地址替換掉,然后按照第四個數組的順序,分別輸出地址、數值和下一地址。
思考:應該是在地址首尾相接并有序存放進第四個數組這一過程中效率太低,但是由于數據是隨機輸入的,也沒有辦法優化查找方法,只能根據遍歷來查找,所以才會超時;第二處是將next地址替換掉根本就是多此一舉,因為上一個元素的next就是下一個元素的address,所以這里也浪費時間遍歷了一遍。綜合考慮下,舍棄此方法。
方法2(參照別人的做法):大體做法與方法1類似,但是優化了查找地址的方法。
首先因為地址是五位數,所以在開始就新建個大小為100000的數組,在第一遍存數據的時候,就根據地址作為下標存入這個數組中,一切輸入都存儲完畢后。根據初始地址,一個一個在地址數組中查找對應的值,并將其存入結構體數組中(結構體有三個變量:address,data,next),最后使用STL中的reverse方法翻轉,然后并輸出結構體數組中的結果即可。具體方法見源代碼。
此次解題過程中用到了新的東西:pair類型,下面來簡要介紹一下。
概念:pair是一種模板類型,其中包含兩個數據值,兩個數據的類型可以不同,基本的定義如下:
pair<int, string> a;
表示a中有兩個類型,第一個元素是int型的,第二個元素是string類型的,如果創建pair的時候沒有對其進行初始化,則調用默認構造函數對其初始化。
pair<string, string> a("James", "Joy");
也可以像上面一樣在定義的時候直接對其初始化。
由于pair類型的使用比較繁瑣,因為如果要定義多個形同的pair類型的時候,可以時候typedef簡化聲明:
typedef pair<string, string> author;
author pro("May", "Lily");
author joye("James", "Joyce");
而如何對pair對象進行操作呢?
1.對于pair類,由于它只有兩個元素,分別名為first和second,因此直接使用普通的點操作符即可訪問其成員
typedef pair<string, string> author;
author pro;
pro.first = "Lily";
pro.second = "Poly";
等同于
pair<string, string> author("Lily", "Poly");
2.生成新的pair對象
可以使用make_pair對已存在的兩個數據構造一個新的pair類型:
int a = 8;
string m = "James";
pair<int, string> newone;
newone = make_pair(a, m);
這里我對pair的理解就是類似結構體一樣的東西,然后提供了first和second作為訪問其中變量的方法。
源代碼
//C/C++實現
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int, int> P;
P addr[100000];
struct node{
int address, data, next;
};
int main(){
int start, n, k, address, data, next;
scanf("%d %d %d", &start, &n, &k);
vector<node> list;
for(int i = 0; i < n; ++i){
scanf("%d %d %d", &address, &data, &next);
P p;
p.first = data;
p.second = next;
addr[address] = p;
}
int tmp = start;
while(tmp != -1){
node n;
n.address = tmp;
n.data = addr[tmp].first;
n.next = addr[tmp].second;
list.push_back(n);
tmp = n.next;
}
for(int l = 0, index = 0; l < list.size() / k; ++l){
reverse(list.begin() + index, list.begin() + index + k);
index += k;
}
int o = 0;
for(; o < list.size() - 1; ++o){
printf("%05d %d %05d\n", list[o].address, list[o].data, list[o + 1].address);
}
printf("%05d %d -1\n", list[o].address, list[o].data);
return 0;
}