首页 > 试题广场 >

反转链表 (25)

[编程题]反转链表 (25)
  • 热度指数:26424 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 146M,其他语言293M
  • 算法知识视频讲解
给定一个常数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是下一结点的地址。


输出描述:
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。
示例1

输入

00100 6 4<br/>00000 4 99999<br/>00100 1 12309<br/>68237 6 -1<br/>33218 3 00000<br/>99999 5 68237<br/>12309 2 33218

输出

00000 4 33218<br/>33218 3 12309<br/>12309 2 00100<br/>00100 1 99999<br/>99999 5 68237<br/>68237 6 -1

本题有一个陷阱,输入的n会大于100000,有一些无效结点需要排除,所以不能以n作为链表长度而是要在排链表时重新计算一遍。

发表于 2017-04-01 17:12:03 回复(1)
 import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int first = sc.nextInt();
		int nc = sc.nextInt();
		ArrayList<Node> ll = new ArrayList<Node>();
		int k = sc.nextInt();
		//节点地址-节点映射
		HashMap<Integer, Node> map = new HashMap<Integer, Node>();
		while(nc != 0){
			int ad = sc.nextInt();
			int val = sc.nextInt();
			int next = sc.nextInt();
			map.put(ad, new Node(ad, val, next));
			nc--;
		}
		sc.close();
		
		//把链表按给出顺序排列,放入集合中
		while(first != -1){
			Node n = map.get(first);
			ll.add(n);
			first = n.next;
		}
		
		//每k位逆转顺序
		for(int i = k; i < ll.size(); i += k){
			int l = i-k;
			int r = i-1;
			while(l < r){
				Node t = ll.get(l);
				ll.set(l, ll.get(r));
				ll.set(r, t);
				l++;
				r--;
			}
		}
		
		//输出结果,地址小于5位前面补0
		for(int i = 0; i<ll.size()-1; i++){
			String str = ""+ll.get(i).address;
			String str2 = ""+ll.get(i+1).address;
			while(str.length() < 5)
				str = "0"+str;
			while(str2.length() < 5)
				str2 = "0"+str2;
			System.out.println(str + " " + ll.get(i).val + " " + str2);
		}
		String str = ""+ll.get(ll.size()-1).address;
		while(str.length() < 5)
			str = "0"+str;
		System.out.println(str + " " + ll.get(ll.size()-1).val + " -1"); 
		
	}
	
	static class Node{
		public Node(int adr, int v, int next){
			address = adr;
			val = v;
			this.next = next;
		}
		int address;
		int val;
		int next;
	}

} 


编辑于 2015-09-10 03:18:42 回复(7)
我是用java 写的.
这个题目思路不是很难
先输入存起来.
然后排序
然后旋转
然后输出

问题是一直tm超时.....

我先后改了几点
1 存起来的时候用 hashmap
2 Node类 里边要用String 存地址. 要不然还得循环 来弄格式.很容易就超时了
3 排序的时候用 ArrayList不用LinkedList ,因为读取更频繁.


 LinkedList<E>

  • get(int index) is O(n)
  • add(E element) is O(1)
  • add(int index, E element) is O(n)
  • remove(int index) is O(n)
  • Iterator.remove() is O(1) <--- main benefit of LinkedList<E>
  • ListIterator.add(E element) is O(1) <--- main benefit of LinkedList<E>

For ArrayList<E>

  • get(int index) is O(1) <--- main benefit of ArrayList<E>
  • add(E element) is O(1) amortized, but O(n) worst-case since the array must be resized and copied
  • add(int index, E element) is O(n - index) amortized, but O(n) worst-case (as above)
  • remove(int index) is O(n - index) (i.e. removing last is O(1))
  • Iterator.remove() is O(n - index)
  • ListIterator.add(E element) is O(n - index)
发表于 2015-11-28 19:32:42 回复(4)
#include <iostream>
#include <algorithm>
#include <vector>
#include <stdio.h>
using namespace std;
struct listnode {
 int data, next;
};
int main() {
 int first, n, k;
 listnode thelist[100002];
 cin >> first >> n >> k;
 int addri;
 for (int i = 0; i<n; i++) {
  cin >> addri;
  cin >> thelist[addri].data >> thelist[addri].next;
 }
 int count = 0;
 vector<int> addr(n + 1, -1);
 addr[0] = first;
 while (addr[count] != -1) {
  count++;
  addr[count] = thelist[addr[count - 1]].next;
 }
 for (int i = 0; i + k<=count; i += k) {
  reverse(addr.begin() + i, addr.begin() + i + k);
 }
 for (int i = 0; i<count - 1; i++) {
  thelist[addr[i]].next = addr[i + 1];
  printf("%05d %d %05d\n", addr[i], thelist[addr[i]].data, thelist[addr[i]].next);
 }
 thelist[addr[count - 1]].next = -1;
 printf("%05d %d -1", addr[count - 1], thelist[addr[count - 1]].data);
}
用一个数组存链表,数组的下标就是地址,再用一个vector来按顺序存链表的下标。
交换顺序的时候只用交换vector里的内容,最后再按顺序将next捋一遍……
你以为我维护的是list,其实我维护的是vector哒!
发表于 2018-02-28 17:02:24 回复(6)
本题有一个最大的陷阱,有的节点是无效的,所以需要重新统计链表的长度。
发表于 2018-03-03 16:29:55 回复(0)
TMD,这题真坑,看完题目立马有思路,写完代码死活AC不过,一直提示越界,后来看了讨论区才发现,TM有无效结点,实际结点会小于输入的n,草。前前后后磨蹭了近4小时,一下午就在这弄这题,***了。
package test;
import java.util.*;

public class Main{
	static class Node{
		String address;
		String value;
		String next;
		
		public Node(String address, String value, String next) {
			this.address = address;
			this.value = value;
			this.next = next;
		}
		
	}
    public static void main(String[] args){
            Scanner sc = new Scanner(System.in);
            String start = sc.next();
            String temp= "";
            int n = sc.nextInt();
            int k = sc.nextInt();
            HashMap<String, Node> map = new HashMap<String, Node>(n);
            for(int i = 0; i < n; i++){
            	temp = sc.next();
            	map.put(temp, new Node(temp, sc.next(), sc.next()));
            }
            int count = 0;//记录真实结点数目
            Node [] nodes = new Node[n];
            Node p = map.get(start);
            
            while(p != null){
            	nodes[count++] = p;  //真实结点就放入数组
            	p = map.get(p.next);
            }
            
            p = map.get(start);
            
            if(count <= 2 || count < k){    //结点数小于等于2 或者真实结点数小于k直接输出
            	for (int i = 0; i < count; i++) {
					System.out.println(nodes[i].address + " " + nodes[i].value + " " + nodes[i].next);
				}
            	return;
            }
            n = count;    //一开始没有意识到有无效结点,就一直以输入的n做结点数,结果疯狂越界
            int i = k - 1;
            for(; i < n - (n % k); i += k){
            	for(int j = i; j > i - k; j--){
            		if(j == i - k + 1){
            			if(i + k < n)
            				System.out.println(nodes[j].address + " " + nodes[j].value 
                    				+ " " + nodes[i + k].address);
            			else
            			System.out.println(nodes[j].address + " " + nodes[j].value 
                				+ " " + nodes[i + 1].address);

            		}else
            			System.out.println(nodes[j].address + " " + nodes[j].value 
            					+ " " + nodes[j - 1].address);
            	}
            }
            i -= k;	
            for(++i; i < n; i++){
            	System.out.println(nodes[i].address + " " + nodes[i].value 
            				+ " " + nodes[i].next);
            }            
    }
}


发表于 2019-08-17 18:26:49 回复(1)

这个题目实在是“一言难尽”,希望大家不要浪费太多时间在题目没有写出的坑上。如果你本地测试良好,但是线上不通过,检查以下坑:

  • 题目输入可能包含无效节点,你需要自行遍历一遍链表来确定节点的真实数量
  • 有效节点数可能小于 K,此时直接输出整个链表不要反转
  • 有效节点数可能小于等于 2,此时也是直接输出(对应第7个检查点)

贴个通过全部测试点的代码,为了处理上面的坑加了一些莫名其妙的判断,大家理解一下。

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        HashMap<String, Node> nodes = new HashMap<String, Node>();

        String beginAddress = in.next();
        int nodeNum = in.nextInt();
        int K = in.nextInt();

        for(int i = 0; i< nodeNum; i++) {
            String address = in.next();
            int data = in.nextInt();
            String nextAddress = in.next();
            nodes.put(address, new Node(address, data, nextAddress));
        }

        int validenodeNum = 0;
        Node countNode = nodes.get(beginAddress);

        while(countNode != null) {
            countNode = countNode.next(nodes);
            validenodeNum++;
        }

        Node judgeNdde = nodes.get(beginAddress);
        if(validenodeNum <= 2 || validenodeNum < K) {

            while(judgeNdde!=null) {
                System.out.println(judgeNdde);
                judgeNdde = judgeNdde.next(nodes);
            }
            return;

        }

        Node prev = nodes.get(beginAddress);
        Node current = prev.next(nodes);
        Node next = current.next(nodes);
        Node beginNode = prev;
        Node prevBeginNode = null;

        Node printNode = null;

        while(validenodeNum >= K) {
            for(int i = 2; i < K; i++) {
                current.nextAddress = prev.address;
                prev = current;
                current = next;
                next = next.next(nodes);
            }

            current.nextAddress = prev.address;

            if(printNode == null)
                printNode = current;

            if(prevBeginNode == null) {
                prevBeginNode = beginNode;
            } else {
                prevBeginNode.nextAddress = current.address;
                prevBeginNode = beginNode;
            }

            if(next == null) {
                beginNode.nextAddress = "-1";
                break;
            }

            beginNode.nextAddress = next.address;
            prev = next;
            current = prev.next(nodes);
            next = current.next(nodes);
            beginNode = prev;

            validenodeNum -= K;
        }

        while(printNode != null) {
            System.out.println(printNode);
            printNode = printNode.next(nodes);
        }


    }

    static class Node {

        String address = "";
        int data = 0;
        String nextAddress = "";

        public Node(String address, int data, String nextAddress) {
            this.address = address;
            this.data = data;
            this.nextAddress = nextAddress;
        }

        @Override
        public String toString() {
            return address + " " + data + " " + nextAddress;
        }

        public Node next(HashMap<String, Node> nodes) {
            return nodes.get(nextAddress);
        }
    }

}
发表于 2019-06-22 22:37:34 回复(0)
#include <iostream>
#include <stack>
#include <iomanip>
using namespace std;
struct node
{
     int x;       //记录下当前的序号
     int next;   //记录下下一个节点的地址
     int index;   //记录下当前的地址
};
 
 int main()
 {
     node list_ans[100000];   //以数组来作为数据结构承载链表
     int first_add = 0, N = 0, K = 0, temp_address = 0;
     int i = 0, j = 0, k = 0;
     stack<node> sta;
     cin >> first_add >> N >> K;
     for (i = 0; i < N; i++)                         //输入数据
     {
         cin >> temp_address;
         list_ans[temp_address].index = temp_address;
         cin >> list_ans[temp_address].x;
        cin >> list_ans[temp_address].next; 
     }
     int  pre = first_add;  //检查数据长度,链表的总长度(坑点不一定为N)
     while (pre != -1)
     {
         k++;
         pre = list_ans[pre].next;
     }
     N = k;       //更新N
     pre = first_add;
     int res = N % K, iter = N / K;   //计算需要翻转的次数,以及最后会剩下多少数
     bool first = true;     
     node temp_node;
     for (i = 0; i < iter; i++)    //需要进行翻转次数的计数
     {
         for (j = 0; j < K; j++)   //从起始地址开始进行入栈操作,进入K个
         {
             sta.push(list_ans[pre]);   
             pre = list_ans[pre].next;
         }
         while (!sta.empty())
         {
             temp_node = sta.top();    //出栈操作,第一个出栈的与后序出栈的操作不同,分开处理
             sta.pop();
             if (first)
             {
                 cout << setfill('0') << setw(5) << temp_node.index << " " << temp_node.x;   
                 first = false;
            }
             else
             {
                 cout << " " << setfill('0') << setw(5) << temp_node.index << endl;
                 cout << setfill('0') << setw(5) << temp_node.index << " " << temp_node.x;
             }
         }
      }
      //非翻转的数据进行如下的顺序输出即可
      for (j = 0; j < res; j++)
      {
          temp_node = list_ans[pre];
          pre = list_ans[pre].next;
          if (first)
         {
             cout << setfill('0') << setw(5) << temp_node.index << " " << temp_node.x; 
            first = false;
        }
         else
         {
            cout << " " << setfill('0') << setw(5) << temp_node.index << endl;
            cout << setfill('0') << setw(5) << temp_node.index << " " << temp_node.x;
         }
      }
      //最后补上空格和 -1 的操作
      cout << " " << -1;
      return 0;
 }
 

发表于 2018-08-29 16:47:23 回复(0)
//两个用例通不过,求大神指导
#include <stdio.h>
typedef struct {
    int data;
    int next;
} Node;
int Reverse(Node *a, int head, int K);
int main()
{
    Node a[100002]={0};
    int N;
    int N1;
    int K;
    int adress;
    int data;
    int next;
    int i;
    int flag = 0;
    int cnt = 0;
    int head;
    int hTmp;
    int count=1;
    scanf("%d %d %d", &hTmp, &N, &K);
    int h = hTmp;
    for(i=0;i<N;i++)
    {
        scanf("%d %d %d", &adress, &data, &next);
        a[adress].data = data;
        a[adress].next = next;
    }
    for(;a[h].next!=-1;)
    {  count++;  h = a[h].next;  }  N = count;  N1 = count;
    while(N>=K)
    {
        hTmp = Reverse(a, hTmp, K);
        if(cnt!=0)
        {  a[flag].next = hTmp;  }  if(cnt==0)
        {  head = hTmp;  }
        cnt++;  for(i=0;i<K;i++)   {    if(i==K-1)    {    flag=hTmp;  }   hTmp = a[hTmp].next;   }
        N-=K;
    }
    
      for(i=0;i<N1;i++)   {   if(a[head].next!=-1)  {  printf("%05d %d %05d\n", head, a[head].data, a[head].next);  }  else  {  printf("%05d %d %d\n", head, a[head].data, a[head].next);  }   head = a[head].next;   }
    return 0;
}
int Reverse(Node *a, int head, int K)
{
    int cnt = 1;
    int tmp;
    int new_ = head;
    int old = a[new_].next;
    while(cnt < K)
    {
        tmp = a[old].next;
        a[old].next = new_;
        new_ = old;
        old = tmp;
        cnt++;
    }
    a[head].next = old;
    return new_;
}

编辑于 2017-12-02 13:46:10 回复(0)
#include<bits/stdc++.h>
using namespace std;
struct lian{
	string address,next;
	long long data;
}s1[100001],s2[100001];

int main(){
	string str;
	int n,k;
	cin>>str>>n>>k;
	int i,l;
	int j=0;
	for(i=0;i<n;i++)cin>>s1[i].address>>s1[i].data>>s1[i].next;
	for(i=0;i<n;i++){
		if(s1[i].address==str){
			s2[j].address=s1[i].address;s2[j].data=s1[i].data;s2[j].next=s1[i].next;break;
		}
	}
	while(s2[j].next!="-1"){
		for(i=0;i<n;i++){
			if(s1[i].address==s2[j].next){
				j++;s2[j].address=s1[i].address;s2[j].data=s1[i].data;s2[j].next=s1[i].next;break;
			}
		}
	}
	j++;
	for(i=k-1;i<j-j%k;i+=k){
		if(i==k-1)cout<<s2[i].address<<' '<<s2[i].data;
		else cout<<' '<<s2[i].address<<"\n"<<s2[i].address<<' '<<s2[i].data;
		for(l=1;l<k;l++){
			cout<<' '<<s2[i-l].address<<"\n"<<s2[i-l].address<<' '<<s2[i-l].data;
		}
	}
	if(j<k){
		for(i=0;i<j;i++){
			cout<<s2[i].address<<' '<<s2[i].data<<' '<<s2[i].next<<endl;
		}
	}
	else {
		for(i=j-j%k;i<j;i++){
			cout<<' '<<s2[i].address<<"\n"<<s2[i].address<<' '<<s2[i].data;
		}
		cout<<" -1"<<endl;
	}
}

23行加上break后就超时了,不加能通过,这是为什么有大佬能帮帮看看嘛
编辑于 2021-02-13 22:43:27 回复(1)
// 这里面的无效结点应该就是有些结点它并不在这个单链表的地址循环中,例如有一个结点的地址为0005,但是没有一个节点的next地址是0005,而且它也不是首结点,所以这个节点就是无效的。
发表于 2020-10-26 15:40:15 回复(0)
//感觉思路挺清晰的
#include<iostream>
using namespace std;
int head, N, K, newStart;
struct LNode{
	int Data; 
	int Next;
}L[100000];

void Reverse(LNode *node, int &head, int k){
	int cnt = 0;			
	int	preLastNode = -1;				//表示前一段待反转区段的最后一个结点 
	int p = head, first, pre, cur, nex;
	while(p != -1){
		cnt++;
		int tmp = node[p].Next;			//记录当前结点的下一个结点,将来反转后的尾结点要指向tmp 
		if( cnt == 1 )					//first为当前反转段的第一个元素
			first = p;			
		if( cnt == k ){
			pre = tmp, cur = first, nex; 
			while(cnt){					//反转cnt次 
				nex = L[cur].Next;
				L[cur].Next = pre;
				pre = cur;
				cur = nex;
				cnt--; 	
			}
			//这里的p为反转后在反转区段中的头结点 
			if( preLastNode == -1)		//第一次反转的时候,需要做特殊处理,将head改变为当前的结点 
				head = p;
			else						//将前一次反转的最后一个结点指向当前结点,防止断链 
				node[preLastNode].Next = p;
			preLastNode = first;	 	 
		}
		p = tmp;						//这里 p = L[p].Next会陷入死循环,因为已经实现反转了  
	}
} 
int main(void){
	scanf("%d %d %d", &head, &N, &K);
	int Address, Data, Next;
	for(int i = 0; i < N; i++){
		scanf("%d %d %d", &Address, &Data, &Next);
		L[Address].Data = Data;
		L[Address].Next = Next;
	}
	int flag = 0;
	Reverse(L, head, K);
	int p = head;
	while(p != -1){
		if(L[p].Next != -1)printf("%05d %d %05d\n", p, L[p].Data, L[p].Next);
		else  printf("%05d %d %d\n", p, L[p].Data, L[p].Next);
		p = L[p].Next;
	}
}

发表于 2020-03-07 20:47:55 回复(0)
#include <stdio.h>

struct node {
	int data, next;
};

int list_reverse(struct node *nodes, int head, int k)
{
	int i, p, new_head, tmp_head;

	for(i = 0, p = head; i < k && p != -1; ++i, p = nodes[p].next)
		;

	if(i < k)
		return head;

	for(i = 0, new_head = -1, tmp_head = head; i < k; ++i) {
		p = tmp_head;
		tmp_head = nodes[tmp_head].next;

		nodes[p].next = new_head;
		new_head = p;
	}

	nodes[head].next = list_reverse(nodes, tmp_head, k);

	return new_head;
}

int main()
{
	int head, n, k, i, addr;
	struct node nodes[100000] = {{0}};

	scanf("%d%d%d", &head, &n, &k);

	for(i = 0; i < n; ++i) {
		scanf("%d", &addr);
		scanf("%d%d", &nodes[addr].data, &nodes[addr].next);
	}

	head = list_reverse(nodes, head, k);

	for(i = head; nodes[i].next != -1;i = nodes[i].next)
		printf("%05d %d %05d\n", i, nodes[i].data, nodes[i].next);

	printf("%05d %d -1\n", i, nodes[i].data);

	return 0;
}

发表于 2020-01-17 00:25:09 回复(0)
12月6号才点开这题,一直找不到BUG,第二天参加乙级考试发现最后一题居然是这道的原题改编。
注意输出的结点不是n个,会有结点没用到。每次传入的addr是当前区块首结点的地址,pre是上一区块的尾结点地址,ta是临时地址变量,同理n即next,p即prev,f即first,!flag时修改fa为第一个区块反转后的首地址,flag时连接上一区块。
顺便祝贺自己裸考拿满分,应该直接报甲级了(没时间刷题,认怂报乙级
#include<cstdio>
struct Node {
    int data, next;
};
Node a[100005];
int flag=0, fa, k, n, t, pre;
void func(int addr) {
    int i, ta=addr;
    for(i=0; i<k; i++) {
        if(ta == -1) break;
        ta = a[ta].next;
    }
    if(i == k) {
        ta = a[addr].next;
        int na, pa = addr;
        for(int i=1; i<k; i++) {
            if(i == k-1){
                if(!flag) {
                    fa = ta;
                    flag++;
                } else  {
                    a[pre].next = ta;
                }
            }
            na = a[ta].next;
            a[ta].next = pa;
            pa = ta;
            ta = na;
        }
        a[addr].next = ta;
        pre = addr;
        func(ta);
    }
}
int main() {
    scanf("%5d %d %d", &fa, &n, &k);
    for(int i=0; i<n; i++) {
        scanf("%5d", &t);
        scanf("%d %5d", &a[t].data, &a[t].next);
    }
    func(fa);
    while(fa != -1) {
        printf("%05d %d ", fa, a[fa].data);
        if(a[fa].next != -1) {
            printf("%05d\n", a[fa].next);
        } else {
            printf("-1\n");
        }
        fa = a[fa].next;
    }
}



发表于 2019-12-08 16:51:15 回复(0)
JavaScript    AC
用到了递归,我没有采用数组作为辅助空间,而是用了一个对象,存放这些结点,好在原地上进行修改
在牛客上测试该题代码,不仅要考虑了一个单链表的情况;
还要考虑当所给的节点中有不在所给开头的单链表中的节点时,应忽略其它节点;
还有,当K = 1, K > 有效节点时,不用反转,直接输出所给开头的单链表。
var arr = readline().split(' ');
var l = arr[0];
var num = arr[1];
var k = arr[2];
var node = {};
for(var i=0;i<num;i++){
    arr = readline().split(' ');
    address = arr[0];
    node[address] = {};
    node[address].data = arr[1];
    node[address].next = arr[2];
}
var nodeNum = 0;
countNode(l);
var count = nodeNum;
 
//反转
function reverse(p,k){
    var tail = p;
    var tmp = node[p].next;
    var previous;
    for(var i=1;i<k;i++){
        previous = tmp;
        tmp = node[previous].next;
        node[previous].next = p;
        p = previous;
    }
    count -= k;
    node[tail].next = count<k?tmp:reverse(tmp,k);
    return p;
}
//计数
function countNode(l){
    p = l;
    for(var i=0;i<num;i++){
        nodeNum++;
        if(node[node[p].next] != undefined){
            p = node[p].next;
        }else{
            break;
        }
    }
}
//打印
function myPrint(l){
    p = l;
    for(var i=0;i<nodeNum;i++){
        console.log(p,node[p].data,node[p].next);
        p = node[p].next;
    }
}
//输出
if(k>nodeNum||k===1){
    myPrint(l);
}else myPrint(reverse(l,k))



发表于 2019-11-29 17:39:56 回复(0)
A, B, C = input().split()
B, C = eval(B), eval(C)
L = [input().split() for i in range(B)]
D = {i[0]:i for i in L}
p = A
L = [D[p]]
while D[p][2] != '-1':
    p = D[p][2]
    L.append(D[p])
L = [i[0] for i in L]
L = [L[i:i+C] for i in range(0, len(L), C)]
L = [reversed(i) if len(i) == C else i for i in L]
L = ' '.join([' '.join(i) for i in L]).split()
L = [D[i] for i in L]
for i, j in enumerate(L):
    j[2] = L[i + 1][0] if i != len(L) - 1 else '-1'
for i in L:
    print(' '.join(i))

编辑于 2019-08-25 17:49:27 回复(0)

参考了前面的几个朋友的回答,想明白了有几个坑:

1.虽然给定了总节点数N,但不是所有的节点都连在链表上,有很多废节点。

2.链表上的有效节点数num需要自己统计。

3.题目中只给定了K<=N,但N并不是有效节点数,所以存在K>有效节点数num,链表不需要翻转的情况。(感觉这里有点故意干扰你的意思)

解决思路:

构造一个新的链表(只需记录头尾则可),从头开始遍历原链表,每次构造一个长度为k的小链表,加入到新链表中,期间记录遍历的节点数目,最后不满足k个节点时,直接将节点连入新链表中则可。

#include <stdio.h>

struct Node
{
    int data;
    int next;
};

Node a[100010];

int main()
{
    int n;
    int k;
    int first_add;

    scanf("%d%d%d", &first_add, &n, &k);

    int t_add;
    int t_data;
    int t_next;

    for(int l = 0; l< n; l++)
    {
        scanf("%d%d%d", &t_add, &t_data, &t_next);
        a[t_add].data = t_data;
        a[t_add].next = t_next;
    }

    //num 用于计算链表中的有效节点数目 
    int num = 0;
    int e = first_add;
    while(e!= -1)
    {
        e= a[e].next;
        num ++;
    }

    //i记录已经连到全局新链表中的节点的数目 
    int i = 0;

    //p用于遍历链表 
    int p = first_add;

    //l_head , l_tire指向全局新链表的头和尾,
    //初始时没有节点,均赋值为-2 
    int l_head = -2;
    int l_tire = -2;

    while(p!= -1)
    {
        //如果有效节点数 < k, 则整个链表无需翻转,直接给l_head赋值则可 
        if(num < k)
        {
            l_head = p;
            break;
        }

        //需要翻转,这里是到最后,剩余节点数目少余k个,将节点直接接在全局新链表则可。 
        if(num - i < k)
        {
            //后面直接连上
            a[l_tire].next = p;

            break;
        }

        //else
        //否则长度大于k,构造一个长度为k的翻转的链表,t_head,t_tire指向头尾,将其连接在全局链表的后面 
        int t_head = p;
        int t_tire = p;

        int q = a[p].next;
        a[p].next = -1;

        for(int m = 0; m<k-1; m++)
        {
            int tmp = a[q].next;
            a[q].next = t_head;
            t_head = q;

            q= tmp;
        }

        //加入全局新链表 
        if(l_tire == -2)
        {
            l_tire = t_tire;
        }
        else
        {
            a[l_tire].next = t_head;
            l_tire = t_tire;
        }

        if(l_head == -2)
        {
            l_head = t_head;
        }

        //p后移,i表示已经加入链表中的节点数,+k 
        p = q;
        i = i + k;
    } 

    //从l_head输出新链表 
    int w = l_head;
    while(w!=-1)
    {
        if(a[w].next != -1)
            printf("%05d %d %05d\n", w, a[w].data, a[w].next);
        else
        {
            printf("%05d %d %d\n", w, a[w].data, a[w].next);
        }
        w = a[w].next;
    }

    return 0;
}
编辑于 2019-03-01 17:59:49 回复(1)
out = []
lst = [None for i in range(100001)]
st,num,k = map(int,input().split()) 
for i in range(num):
    t = list(map(int,input().split()))
    lst[t[0]] = [t[1],t[2]]
while st!=-1:
    out.append([st,lst[st][0]])
    st = lst[st][1]
time = len(out)//k
for i in range(time):
    te = out[i*k:i*k+k]
    te.reverse()
    out[i*k:i*k+k] = te
for i in range(len(out)-1):
    print("%05d"%out[i][0]+" "+str(out[i][1])+" "+"%05d"%out[i+1][0])
print("%05d"%out[len(out)-1][0]+" "+str(out[len(out)-1][1])+" "+"-1")
想说的注意事项是,给出的链表数据有可能不止一个,这个时候需要找到当前的链表。
发表于 2018-12-20 15:18:09 回复(0)
#include <bits/stdc++.h>
using namespace std;

#define MAXSIZE 100005   //最大为五位数的地址

struct LinkNode   //使用顺序表存储数据data和下一地址next
{
   int data;
   int next;
};

int main()
{
    vector<LinkNode> v(MAXSIZE);
    int Head, N, K;
    cin >> Head >> N >> K;   //输入头地址 和 N,K
    for (int i = 0; i < N; i++)
    {
        int temp;   //用来存放结点地址的临时变量
        cin >> temp;   //这里不能和下一行写成一行,一定要先读取完temp
        cin >> v[temp].data >> v[temp].next;
    }
    int count = 0;  //count用来存储能够首尾相连的节点数
    int p = Head;   //p指示当前结点
    int List[MAXSIZE];   //存储可以连接上的顺序表
    while(p != -1)
    {
        List[count++] = p;
        p = v[p].next;
    }
    for (int i = 0; i + K <= count; i += K)  //每K个节点做一次翻转
    {
        reverse(&List[i],&List[i+K]);
    }
    for (int i = 0; i < count-1; i++)
    {
        printf("%05d %d %05d\n",List[i],v[List[i]].data,List[i+1]);
    }
    printf("%05d %d -1\n",List[count-1],v[List[count-1]].data);
    return 0;
}

发表于 2018-12-08 11:12:47 回复(0)
#include<stdio.h>

typedef struct
{
    int address;
    int data;
    int next;
}node;

void reverse(int a[],int l,int h)//翻转 
{
    int t=0;
    while(l<h)
    {
        t=a[l];
        a[l]=a[h];
        a[h]=t;
        l++;
        h--;
    }
}

int main()
{
    int a,b,c,j=0,i=0;
    scanf("%d%d%d",&a,&b,&c);
    node no[b],no1[b];
    int temp[b],t;
    
    for(i=0;i<b;i++)
    {
        scanf("%d",&no[i].address);
        scanf("%d",&no[i].data);
        scanf("%d",&no[i].next);
    }
    i=0;

    
    
    t=a;
    
    
    while(j<b)//找出顺序 
    {
        for(i=0;i<b;i++)
        {
        if(t==no[i].address)
        {
            temp[j++]=no[i].data;
            t=no[i].next;
        }
        }
    }
                
    for(i=0;i+c-1<b;i=i+c)
    {
        reverse(temp,i,i+c-1);    
     } 
    j=0; 
    
    
    while(j<b)//找出顺序 
    {
        for(i=0;i<b;i++)
        {
        if(temp[j]==no[i].data)
         {
             no1[j].data=temp[j];
             no1[j].address=no[i].address;
             j++;
         }
        }
    }
     
     j=0;
     for(i=0;i<b-1;i++)
     {
         no1[i].next=no1[i+1].address;
     }
     
     no1[b-1].next=-1;
     
     for(i=0;i<b-1;i++)
     {
         printf("%05d %d %05d\n",no1[i].address,no1[i].data,no1[i].next);
     }
    printf("%05d %d %d\n",no1[i].address,no1[i].data,no1[i].next);
    
    

     
     
    

} 超时了······     
发表于 2018-02-27 21:38:01 回复(0)