【PAT】A1074 Reversing Linked List【链表】

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.

Sample Input:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

Sample Output:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

题意

给出链表的起始地址,长度和K。将链表从头开始,每K个为一组进行逆置,不足K的剩余节点(如果有的话),不进行逆置。

思路

  • 第一步,读取并预处理。使用一个int型的数组next来存储每个结点的下一个结点,然后从起始地址开始遍历。遍历的同时依次将地址加入到arr这个一维的int数组中。执行完这个遍历过程后,无效的结点将被忽略,同时所有的结点的地址被有序的存放在arr中。
  • 第二步,拟置输出。首先计算组数,然后从每组的最后一个结点开始输出信息,它在arr中的前一个元素就是它拟置后next的地址(因为经过第一步我们已经将地址有序排列了)。这里要注意对于每一组的最后一个元素,有两种情况。
    • 它是最后一组。如果它同时也是整个链表最后一个,它的next是-1。算法结束。否则它应连接到在arr下一个元素,并将剩余的元素输出。
    • 它不是最后一组。它应该连接到下一组中的最后一个元素(因为下一组也将被拟置)。

代码

#include 
#define MAX 100000
int main() {
    int next[MAX], value[MAX], arr[MAX], cnt = 0;
    int S, N, K;
    scanf("%d %d %d",&S, &N, &K);
    for(int i = 0, address; i < N; i++){
        scanf("%d", &address);
        scanf("%d", &value[address]);
        scanf("%d", &next[address]);
    }
    for(int x = S; x != -1; x = next[x]){
        arr[cnt++] = x;
    }
    if(cnt == 1){
        printf("%05d %d -1\n", arr[0], value[arr[0]]);
        return 0;
    }
    
    int group = K > 0 ? cnt / K : 0;
    for(int i = 0, t, high, low; i < group; i++){
        low = i * K;
        high = low + K - 1;
        for(int j = high; j > low; j--){
            t = arr[j];
            printf("%05d %d %05d\n", t, value[t], arr[j - 1]);
        }
        t = arr[low];
        if(i == group - 1){ // 如果是最后一组,则连接到逆置前当前组最后一个的下一个或者-1(它可能同时也是整个链表的最后一个)
            if(high == cnt - 1){// 如果是最后一个,next为-1
                printf("%05d %d -1\n", t, value[t]);

            }else{
                printf("%05d %d %05d\n", t, value[t], arr[high + 1]);
            }
            
            // 输出后面的元素
            for(int j = high + 1, t; j < cnt; j++){
                t = arr[j];
                if(j == cnt - 1){
                    printf( "%05d %d -1\n", t, value[t]);
                }else{
                    printf("%05d %d %05d\n", t, value[t], next[t]);
                }
            }
        }else{ // 否则连接到下一组拟置前的最后一个(因为它在拟置后将是下一组的第一个)
            printf("%05d %d %05d\n", t, value[t], arr[high + K]);
        }
    }

    return 0;
}

你可能感兴趣的:(PAT)