【2019年数据结构真题】


【2019统考真题】设线性表L= (a1,a2,a3,...,an-2,an-1,an)采用带头结点的单链表保存,链表中的结点定义如下:

c 复制代码
typedef struct node{
    int data;
    struct node*next;
}NODE;

请设计一个空间复杂度为0(1)且时间上尽可能高效的算法,重新排列L中的各结点,得到线性表 L2 = (a1,an,a2,an-1,a3,an-1...)

要求:

  1. 给出算法的基本设计思想。

  2. 根据设计思想,采用C或C++语言描述算法,关键之处给出注释。

  3. 说明你所设计的算法的时间复杂度

题目信息:

  • 空间复杂度为O(1)且时间上尽可能高效-----尽量不适用栈,队列等辅助结构
  • 带有头节点,不用单独处理第一个结点

方法一:

c 复制代码
void ans(Node* L, int n){
    int t=(n+1)/2;	//即n/2向上取整
    Node* pre=L, p, q, qq;	//q为指向后半段链的指针
    for (int i=0; i<t; i++)
        pre=pre->next;	//pre指向a⌈n/2⌉ 
    q=pre->next;	//q指向a⌈n/2⌉+1
    pre->next=null;	//a⌈n/2⌉的下一个结点为空
    len=n-t;	//后一半链长度
    for (int i=len; i>0; i--){	//一个一个重新插入
        pre=L;
        for (int j=0; j<i; j++)	//找到插入位置
            pre=pre->next;
        p=pre->next;	//pre是插入位置
        pre->next=q;	//插入q
        qq=q->next;	//qq暂存q的下一个结点
        q->next=p;	//q下一个结点是插入位置后的点
        q=qq;	//q指向qq所指结点
    }
}
可这么理解:

给定一个单链表 L:L0→L1→...→Ln-1→Ln ,

将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→...

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.

示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

算法的基本思想:

  1. 快慢指针找中点,将原链表切分成两段
  2. 将后面的链表翻转
  3. 将第二个链表的每个结点依次插在第一个链表的后面

\

比如:1->2->3->4->5->null

切分变成:1->2->3->null ; 4->5->null ;

将 4->5 翻转变成5->4;

插入变成:1->5->2->4->3->null;

c 复制代码
class Solution {
  public:
    void reorderList(ListNode* head) {
        if (head == NULL || head->next == NULL)
            return;
//快慢指针分出两段
        ListNode* slow = head, *fast = head;
        while (fast->next && fast->next->next) {
            slow = slow->next;
            fast = fast->next->next;
        }
//后端反转
        ListNode* needReverser = slow->next;
        slow->next = NULL;
        needReverser = reverse(needReverser);
//插入前端缝隙
        ListNode* cur = head;
        while (cur && needReverser) {
            ListNode* curSecond = needReverser;
            needReverser = needReverser->next;
            ListNode* nextCur = cur->next;
            curSecond->next = cur->next;
            cur->next = curSecond;
            cur = nextCur;
        }
    }
    ListNode* reverse(ListNode* head) {
        ListNode* p1 = NULL;
        ListNode* p2 = head;
        ListNode* p3 = p2;
        while (p2) {
            p3 = p2->next;
            p2->next = p1;
            p1 = p2;
            p2 = p3;
        }
        return p1;
    }
};
相关推荐
少许极端28 分钟前
算法奇妙屋(五)-链表
数据结构·算法·链表
木子.李3471 小时前
数据结构-算法C++(额外问题汇总)
数据结构·c++·算法
程序员莫小特2 小时前
老题新解|计算2的N次方
开发语言·数据结构·算法·青少年编程·信息学奥赛一本通
十重幻想4 小时前
PTA6-1 使用函数求最大公约数(C)
c语言·数据结构·算法
青岛少儿编程-王老师4 小时前
CCF编程能力等级认证GESP—C++5级—20250927
java·数据结构·c++
胖咕噜的稞达鸭7 小时前
C++中的父继子承:继承方式实现栈及同名隐藏和函数重载的本质区别, 派生类的4个默认成员函数
java·c语言·开发语言·数据结构·c++·redis·算法
笑口常开xpr7 小时前
【C++】模板 - - - 泛型编程的魔法模具,一键生成各类代码
开发语言·数据结构·c++·算法
立志成为大牛的小牛8 小时前
数据结构——十四、构造二叉树(王道408)
数据结构·笔记·学习·程序人生·考研
笑口常开xpr8 小时前
【C++继承】深入浅出C++继承机制
开发语言·数据结构·c++·算法
HQChart9 小时前
HQChart使用教程30-K线图如何对接第3方数据46-DRAWTEXT_FIX数据结构
数据结构·hqchart·k线图