2018.3.26
输入一个乱序表,每个结点包含当前地址、值、下一地址。给定乱序表结点数N和翻转周期K,把输入的乱序表按照周期K进行翻转。注意几个测试点:1.小于周期K的尾巴不翻转,2.有不在链表上的多余输入结点,3.取最大值N=100000时运行时间不能过长。
Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.
Input Specification:
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤10^5) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:
Output Specification:
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
总体思路是先对输入进行排序,再进行翻转,思路很简单,但是很难降低时间复杂度。
这道题做了几天,因为总是通不过N=100000的测试样例,显示运行超时,主要原因是排序时间过长。方案一是最先是实现方法,方案二是参考网络上的可行方案修正排序后的做法,排序算法可以说是一致的了,可是还是运行超时,考虑是用vector容器创建与删除对象过程过于复杂。
以下是利用vector实现的2个方案:
方案一:
// Reversing_Linked_List.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <iostream> #include <iomanip> #include <vector> using namespace std; class Element { public: long address; int data; long next; }; void Read(long& begin, long& total, vector<Element>& elements); void Print(vector<Element>& elements); void Reversing(long &revnum, vector<Element>& elements); int main() { long begin; long total; long revnum; vector<Element> elements; cin >> begin >> total >> revnum; Read(begin, total, elements); Reversing(revnum, elements); Print(elements); system("pause"); return 0; } void Read(long& begin, long& total, vector<Element>& elements) { for (long i = 0; i < total; i++) { Element e; cin >> e.address >> e.data >> e.next; elements.push_back(e); } long tail = begin; for (long i = 0;i < total;i++) { if (tail == -1) { if (i != total - 1) { elements.erase(elements.begin() + i, elements.begin() + total); } break; } for (long j = i;j < total;j++) { if (elements[j].address == tail) { tail = elements[j].next; if (i != j) { Element t = elements[j]; elements[j] = elements[i]; elements[i] = t; } break; } } } } void Print(vector<Element>& elements) { for (long i = 0;i < elements.size();i++) { cout << setw(5) << setfill('0') << elements[i].address; cout << " " << elements[i].data << " "; if (elements[i].next == -1) { cout << elements[i].next << endl; } else { cout << setw(5) << setfill('0') << elements[i].next << endl; } } } void Reversing(long &revnum, vector<Element>& elements) { for (long i = 0; i < elements.size();i += revnum) { if (i + revnum > elements.size())break; long mid = i + revnum / 2; long tail = i + revnum - 1; for (long j = i;j < mid;j++) { Element t = elements[j]; elements[j] = elements[tail]; elements[tail] = t; tail--; } } for (long i = 0;i < elements.size()-1;i++) { elements[i].next = elements[i + 1].address; } elements[elements.size() - 1].next = -1; }
方案二:
// Reversing_Linked_List.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <iostream> #include <iomanip> #include <vector> using namespace std; class Element { public: int address; int data; int next; }; void Read(int& begin, int& total, vector<Element>& elements); void Print(vector<Element>& elements); void Reversing(int &revnum, vector<Element>& elements); int main() { int begin; int total; int revnum; vector<Element> elements; cin >> begin >> total >> revnum; Read(begin, total, elements); Reversing(revnum, elements); Print(elements); system("pause"); return 0; } void Read(int& begin, int& total, vector<Element>& elements) { vector<Element> e2; for (int i = 0; i < total; i++) { Element e; cin >> e.address >> e.data >> e.next; e2.push_back(e); } //顺序插入 int tail = begin; while (tail!=-1) { int i = 0; int count = 0; int size = e2.size(); while(count != size){ if (e2[i].address == tail) { elements.push_back(e2[i]); tail = e2[i].next; e2.erase(e2.begin() + i); } else { i++; } count++; } } } void Print(vector<Element>& elements) { for (long i = 0; i < elements.size(); i++) { //输出补零 cout << setw(5) << setfill('0') << elements[i].address; cout << " " << elements[i].data << " "; if (elements[i].next == -1) { cout << elements[i].next << endl; } else { cout << setw(5) << setfill('0') << elements[i].next << endl; } } } void Reversing(int &revnum, vector<Element>& elements) { //翻转 for (int i = 0; i < elements.size(); i += revnum) { if (i + revnum > elements.size())break; int mid = i + revnum / 2; int tail = i + revnum - 1; for (int j = i; j < mid; j++) { Element t = elements[j]; elements[j] = elements[tail]; elements[tail] = t; tail--; } } //依次改next值 for (int i = 0; i < elements.size() - 1; i++) { elements[i].next = elements[i + 1].address; } elements[elements.size() - 1].next = -1; }
可行方案:
参考https://www.cnblogs.com/kuotian/p/5269434.html
#include <stdio.h> #include <stdlib.h> typedef struct Node { int address; int data; int nextAddress; struct Node *next; }Node; typedef struct Node *LinkList; int main() { //排序前 LinkList L1, p1, q1; L1 = (LinkList)malloc(sizeof(Node)); //创建头指针 L1->next = NULL; int firstAddress; int N, K;//N为总结点数 K为需翻转的数 scanf("%d %d %d", &firstAddress, &N, &K); p1 = L1; for(int i = 0; i < N; i++) { q1 = (LinkList)malloc(sizeof(Node)); scanf("%d %d %d",&q1->address, &q1->data, &q1->nextAddress); p1->next = q1; p1 = q1; } p1->next = NULL; //排序后 LinkList L2, p2; L2 = (LinkList)malloc(sizeof(Node)); //创建头指针 L2->next = NULL; int count = 0; int findAddress = firstAddress; p2 = L2; while(findAddress != -1) { //while(count < N) {有多余结点不在链表上没通过 q1 = L1; while(q1->next) { if(q1->next->address == findAddress) { p2->next = q1->next; q1->next = q1->next->next; p2 = p2->next; count++; // printf("count = %d\n",count); findAddress = p2->nextAddress; // printf("findAddress = %d\n",findAddress); }else { q1 = q1->next; } } } p2->next = NULL; //Reversing LinkList L3, p3, q3, tail; L3 = (LinkList)malloc(sizeof(Node)); //创建头指针 L3->next = NULL; //将L2以头插法插入L3 int n = count; //防止有多余结点影响 n=N 会影响 int k = K; p3 = L3; p2 = L2; while(n >= k) { n -= k; for(int i = 0; i < k; i++) { p3->next = p2->next; p2->next = p2->next->next; if(i == 0) tail = p3->next; else p3->next->next = q3; q3 = p3->next; } p3 = tail; } p3->next = L2->next; p3 = L3->next; while(p3->next) { printf("%05d %d %05d\n",p3->address, p3->data, p3->next->address);//不到五位数用0补全 p3 = p3->next; } printf("%05d %d -1\n",p3->address, p3->data); return 0; }