2019年全国研究生入学考试计算机学科专业基础综合(408)数据结构编码题

有一个带头节点的单向链表 ( a 1 , a 2 , … , a n − 1 , a n ) (a_1, a_2,\dots,a_{n-1},a_n) (a1,a2,,an1,an) n n n为偶数,使用空间复杂度为 O ( 1 ) O(1) O(1)的算法使其变成 ( a 1 , a n , a 3 , a n − 2 , … , a 4 , a n − 1 , a 2 ) (a_1, a_{n},a_3,a_{n-2},\dots,a_4,a_{n-1},a_2) (a1,an,a3,an2,,a4,an1,a2)


有同学说,我看错题目了,我也不知道看错了没,都写出来吧,原题有可能是变成 ( a 1 , a n , a 2 , a n − 1 , a 3 …   ) (a_1, a_{n},a_2,a_{n-1},a_{3}\dots) (a1,an,a2,an1,a3)


struct Node {
	int data;
	Node *next;
}

普通模拟就好。因为要求空间复杂度为 O ( 1 ) O(1) O(1),有点复杂的可能就是指针间的操作。

模拟步骤:

  • 把单向链表分成两部分, ( a 1 , a 3 , … , a n − 1 ) (a_1,a_3,\dots,a_{n-1}) (a1,a3,,an1) ( a 2 , a 4 , … , a n ) (a_2,a_4,\dots,a_{n}) (a2,a4,,an)
  • 头插法逆转 ( a 2 , a 4 , … , a n ) (a_2,a_4,\dots,a_{n}) (a2,a4,,an),变成 ( a n , a n − 2 , … , a 2 ) (a_n,a_{n-2},\dots,a_{2}) (an,an2,,a2)
  • 合并这两部分。

如果是我看错了题目,那么这个题就更加简单了,有差别的只是第一步,走到中点,然后断开链表,一分为二,这个操作要比我的版本的题目的第一步操作要简单。

下面给出我的版本的代码,有可能是原题的版本的代码相差不多,自行实现,这里不在赘述。

Node *reverse(Node *root)
{
    // 少于等于2个结点直接返回
    if (root == NULL || root->next == NULL || root->next->next == NULL)
        return root;
    Node *listA = root, *listB = root->next;
    // 1 : 分离
    Node *pa = listA, *pb = listB;
    for (; pb->next != NULL; ) {
        pa->next = pa->next->next;
        pa = pa->next;
        pb->next = pa->next;
        pb = pb->next;
    }
    pa->next = NULL;
    // 2 : 头插法
    pb = listB->next;
    listB->next = NULL;
    for (Node *p = pb; p != NULL; ) {
        Node *tn = p->next;
        p->next = listB;
        listB = p;
        p = tn;
    }
    // 3 : 合并
    pa = listA, pb = listB;
    for ( ; pb != NULL; ) {
        Node *ta = pa->next, *tb = pb->next;
        pa->next = pb;
        pb->next = ta;
        pa = ta;
        pb = tb;
    }
    return listA;
}

测试代码如下:

int main()
{
    Node head, *root = &head;
    root->next = NULL;
    for (int i = 1; i < 11; ++i) {
        root->next = new Node;
        root->next->data = i;
        root = root->next;
        root->next = NULL;
    }
    for (Node *p = head.next; p != NULL; p = p->next)
        printf("%d ", p->data);
    puts("");

    head.next = reverse(head.next);

    for (Node *p = head.next; p != NULL; p = p->next)
        printf("%d ", p->data);
    puts("");
    return 0;
}

输出:

PS C:\Users\FlushHip\Desktop\TTT> .\a.exe
1 2 3 4 5 6 7 8 9 10
1 10 3 8 5 6 7 4 9 2
PS C:\Users\FlushHip\Desktop\TTT>

这里就算不给出 n n n是偶数这个条件也很好办,只不过结束的条件不一样,且结束后还有一两步操作而已。

空间复杂度 O ( 1 ) O(1) O(1),时间复杂度 O ( n ) O(n) O(n)

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值