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:
Address Data Next
where Address is the position of the node, Data is an integer, and Next is the position of the next node.
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
#include
#include
#include
#include
using namespace std;
class Element {
public:
long address;
int data;
long next;
};
void Read(long& begin, long& total, vector& elements);
void Print(vector& elements);
void Reversing(long &revnum, vector& elements);
int main()
{
long begin;
long total;
long revnum;
vector 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& 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& 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& 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
#include
#include
#include
#include
using namespace std;
class Element {
public:
int address;
int data;
int next;
};
void Read(int& begin, int& total, vector& elements);
void Print(vector& elements);
void Reversing(int &revnum, vector& elements);
int main()
{
int begin;
int total;
int revnum;
vector 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& elements) {
vector 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& 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& 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
#include
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;
}
#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#