1074 Reversing Linked List

1074 Reversing Linked List

题目描述

Given a constant K K K and a singly linked list L L L, you are supposed to reverse the links of every K K K elements on L L L. For example, given L L L being 1→2→3→4→5→6, if K K K=3, then you must output 3→2→1→6→5→4; if K K 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 ( ≤ 1 0 5 ) N (≤10^5) N(105) which is the total number of nodes, and a positive K ( ≤ N ) K (≤N) 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 N 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为单位逐段逆转长度为 N N N的链表,若最后一段长度小于 K K K则不逆转。

根据输入数据,我们可以使用静态链表(数组)来储存链表。
进行链表逆转时,注意到每一段逆转之后的链表尾结点都要接上下一段逆转之后的链表头结点,显然这应该是一个递归过程。所以我采用递归的方式进行逆转,即向下递归时逐段从前往后逆转,向上递归时将逆转之后的头结点与上一段尾结点进行连接。

本题需注意:

  1. K K K个结点逆转一次,而不是仅逆转前 K K K个结点

  2. 判断是否结束递归时需要比较待逆转子链表长度与 K K K,直接访问链表长度是一个 O ( N ) O(N) O(N)的过程,而每段都要访问一次,测试点5会超时,所以应该在递归逆转之前将链表长度求出,将其作为参数进行传递。

  3. 进行输出时需要注意尾结点的格式:-1

这个题目我写过两次,第一次用C写的,第二次用C++写的,思路相同,形式也差不多

源码

// c++版本
#include<cstdio>
using namespace std;

struct ListNode {
    int data;
    int next;
};
class LinkedList{
public:
    int head;
    LinkedList(int node=-1):head(node){}
    void readList(int N);
    void reverseK(LinkedList &l, int len, int K);
    void printList(LinkedList& l);
    int size();
    static const int N = 100000;
    static ListNode mem[N];
    static void initMemory();
};
ListNode LinkedList::mem[N];
void LinkedList::initMemory()
{
    for (int i = 0; i < N; i++)
    {
        mem[i].next = -1;
    }
}
void LinkedList::readList(int N)
{
    int address, data, next;
    for (int i = 0; i < N; i++)
    {
        scanf("%d %d %d", &address, &data, &next);
        if(address >= 0)
            mem[address] = { data, next };
    }
}
int LinkedList::size()
{
    int len = 0, flag =0;
    for (int i = this->head; i != -1 && !flag; i = mem[i].next)
    {
        len++;
        if (mem[i].next == this->head)
        {
            flag = 1;
        }
    }
    return len;
}
void LinkedList::reverseK(LinkedList& l, int len, int K)
{
    if (len < K)
        return;
    int newhead=l.head, oldhead=l.mem[l.head].next, tail = l.head;
    int seq = tail;

    for (int i = 0; i < K; i++)
    {
		l.mem[newhead].next = seq;
		seq = newhead;
		newhead = oldhead;
		oldhead = l.mem[oldhead].next;
    }
    l.head = seq;
    LinkedList sub_l(newhead);
    reverseK(sub_l, len-K,  K);
    l.mem[tail].next = sub_l.head;
}
void LinkedList::printList(LinkedList& l)
{
    int flag = 0;
    for (int i = l.head; i != -1 && !flag; i = mem[i].next)
    {
        printf("%05d %d ", i, mem[i].data);
        if (mem[i].next == -1) {
            printf("%d\n", mem[i].next);
        }
        else {
            printf("%05d\n", mem[i].next);
        }
        if (mem[i].next == head)
            flag = 1;
    }
}

int main()
{
    LinkedList::initMemory();
    LinkedList l;
    int N, K;
    scanf("%d %d %d", &l.head, &N, &K);
    l.readList(N);
    l.reverseK(l, l.size(), K);
    l.printList(l);

    return 0;
}
// C版本
#include<stdio.h>

#define Memory_Length 100000
#define Min(a, b) (a<b ? a : b)

typedef struct {
    int data; 
    int next;
} Memry_Unit;

Memry_Unit Memory[Memory_Length];

void Initial_Mem(void){
    int i;
    for(i=0; i<Memory_Length-1; i++)
    {
        Memory[i].next=i+1;
    }
    Memory[i].next=0;
}

void Mem_alloc(int l, int n)
{
    int address;
    int next;
    int data;

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

}

int Reverse_List(int l, int n, int k)
{
    if(n<k){
        return l;
    }
    int old, new=l, tail, cut_head;

    tail=new;
    old=Memory[new].next; 
    cut_head=Memory[old].next;
    for(int i=0; i<k-1; i++)
    {
        Memory[old].next=new; 
        new=old;
        old=cut_head;
        cut_head=Memory[old].next;
    }
    Memory[tail].next=Reverse_List(old, n-k, k);

    return new;
}

void Print_List(int l)
{
    while(l!=-1)
    {
        if(Memory[l].next == -1){
            printf("%05d %d %-d", l, Memory[l].data, Memory[l].next);
        }else{
            printf("%05d %d %05d\n", l, Memory[l].data, Memory[l].next);
        }
        l=Memory[l].next;
    }
}

int Length(int l)
{
    int cnt=0;
    while(l!=-1){
        cnt++;
        l=Memory[l].next;
    }
    return cnt;
}

int main()
{
    int l; 
    int len;
    int re_len;
    scanf("%d %d %d", &l, &len, &re_len);
    Mem_alloc(l, len);
    len=Length(l);
    Print_List(Reverse_List(l, len, re_len));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值