11.回文链表(两种方法)(双指针+头插)

面试题 02.06. 回文链表 试试这题

编写一个函数,检查输入的链表是否是回文的

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

思路:首先要得到链表的一半,然后将前半部分或后半部分的链表逆置,然后和前面的另一半比对,若相同则是回文的,反之则不是,细节请看代码

第一种方法:找中间结点+头插逆置
求出结点总个数然后即可以找到中间位置,这样效率不高,但是可以把链表的结构掌握的很清楚

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode Node;
bool isPalindrome(struct ListNode* head){
    Node* cur = head;
    int cnt = 0;
    while(cur)
    {
        cur = cur->next;
        cnt++;
    }
    cur = head;//记得要将cur在返回head结点
    int jud = cnt % 2;//判断结点的个数是奇数还是偶数
    //定义一个number保留中间结点的位置
    int number = cnt = cnt / 2;
    while(number--)
    {
        cur = cur->next;
    }
    if(jud == 1)
        cur = cur->next;//如果是奇数个结点,那么就跳过中间结点
    //开始头插逆置
    Node* newhead = NULL;
    while(cnt--)
    {
        Node* next = cur->next;
        cur->next = newhead;
        newhead = cur;
        cur = next;
    }
    while(newhead && head)
    {
        if(head->val != newhead->val)
            return false;
        newhead = newhead->next;
        head = head->next;
    }
    return true;
}

第二种方法:双指针+头插逆序
利用fast指针和slpw指针,fast指针每次做两步,slow指针每次走一步,然后两个指针同时遍历链表,当fast指针走完链表的时候,这时slow指针只走了链表的一半,这就是上面的优化,后面的头插比对有一点点不一样,我会在代码中提示出来。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode Node;
bool isPalindrome(struct ListNode* head){
    if(head == NULL || head->next == NULL)
        return true;
    Node* fast = head;
    Node* slow = head;
    Node* prev = head;//保留链表的中间结点的上一个结点,为了让两个链表分开
    //因为节点数可能是奇数可能是偶数,所以要用fast(偶数)fast->next(奇数)判断
    while(fast && fast->next)
    {
        prev = slow;
        fast = fast->next->next;
        slow = slow->next;
    }


    //将前半部分链表和后半部分分开,易错点
    prev->next = NULL;


    //头插后半段的链表
    Node* newhead = NULL;
    while(slow)
    {
        Node* next = slow->next;
        slow->next = newhead;
        newhead = slow;
        slow = next;
    }
    //比对两个链表,但是要注意如果节点数是奇数的话,两个链表的节点数不相同,所以判断的时候要以,前半部分的结束为结束
    while(head)
    {
        if(head->val != newhead->val)
            return false;
        head = head->next;
        newhead = newhead->next;
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hyzhang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值