【408DS算法题】023提高-判断带头结点的链表是否对称

Index

    • 题目
    • 分析实现
    • 总结

题目

基础:给定链表的头结点,判断双循环链表是否对称。

提高:给定链表的头结点,判断单链表是否对称。


分析实现

首先分析基础题目:双循环链表的对称判断

双循环链表可以方便地访问任意结点的前驱,可直接设置分别指向链表结点的前后指针,不断判断前后指针所指元素是否相等。
当两指针相遇/交错的时候,对称性判断完毕,具体实现如下:

bool isSymmetric(DLNode *head){
    DLNode *a=head->next, *b=head->prior;
    // 循环至a扫描完前半部分/b扫描完后半部分 - 奇数个结点时a==b, 偶数个结点时a->prior==b
    while(a != b && a->prior != b){
        // 发现不对称
        if(a->val != b->val)
            return false;
        a = a->next;
        b = b->prior;
    }
    return true;
}

下面分析提高题目:单链表的对称判断

单链表没有了访问前驱的能力,因此需要先对原链表进行预处理,以便实现后半段和前半段的比较。所需进行的预处理有:(此处的预处理操作还与之前练习的重新排列链表结点相同)

  1. 得到链表最后一个结点
  2. 将后半部分链表逆置

具体实现如下:

bool isSymmetric(LNode *head){
    if(head->next==NULL || head->next->next==NULL)
        return true;

    LNode *fast=head, *slow=head;
    while(fast->next != NULL){
        slow=slow->next;
        fast=fast->next;
        // fast的移动分两步进行
        if(fast->next)
            fast=fast->next;
    }
    // 修改fast指向后半段的第一个结点
    fast = slow->next;

    // 断开链表前半部分和后半部分, 修改slow指向前半部分的第一个结点
    slow->next = NULL;
    slow = head->next;

    // 用pre、fast、sub 逆置后半段链表
    LNode *sub, *pre=NULL;
    while(fast != NULL){
        sub = fast->next;
        fast->next = pre;
        pre = fast;
        fast = sub;
    }
    // 修改fast指向逆置后的后半部分的第一个结点
    fast = pre;

    // 检验对称性
    while(slow != NULL && fast != NULL){
        if(slow->val != fast->val)
            return false;
        slow = slow->next;
        fast = fast->next;
    }
    return true;
}

总结

以上就是检验链表对称性的实现,在单链表的对称判断中又用到了查找链表中点单链表逆置这两个操作,需要格外注意。

你可能感兴趣的:(算法,链表,数据结构)