234. 回文链表

地址:

力扣icon-default.png?t=M0H8https://leetcode-cn.com/problems/palindrome-linked-list/

题目:

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

示例 1:

输入:head = [1,2,2,1]
输出:true


示例 2:

输入:head = [1,2]
输出:false


 

提示:

链表中节点数目在范围[1, 105] 内
0 <= Node.val <= 9

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:

既然是回文判定,一定是前后值相互比较,如果不相等一定不是回文

因为是单链表,所以没办法同时移动指针,容易想到的是把单链表的值存放到一维数组

这样就可以进行比较

方法一、数组保存值比较

考虑测试用例的不同情况,可能前序指针不会超过,或者超过数组半数

所以最后还是以数组长度为界限

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


bool isPalindrome(struct ListNode* head){
    if(head == NULL)
        return true;

    int cnt = 0;
    int k = 0;
    struct ListNode *p = head;

    while(p)
    {
        p = p->next;
        cnt++;
    }

    int *array = (int *)malloc(sizeof(int) * cnt);
    
    p = head;
    while(p)
    {
        array[k++] = p->val;
        p = p->next;
    }

    for(int i = 0, j = cnt - 1; i < cnt; i++, j--)
    {
        if(array[i] != array[j])
        {
            free(array);
            return false;
        }
    }

    free(array);
    return true;
}

方法二、反转链表比较

如果能够找到链表的中间点,那么链表后半部的子链表我们可以进行反转

反转链表的具体操作可以查看:206. 反转链表

反转完成后相当于两个子链表的比较,就很容易

引入fast(每次 2 步),slow(每次 1 步)指针

当 fast 到达末尾时,slow 位于中点,这里要区分 链表个数的奇偶性,才能处理好 slow 的位置进行反转

示例:

奇数链表

fast 移动到末尾时的样子

把 slow 移动到下一个节点

如果链表是偶数的话,最后样子是:

 

 

以 slow 开始作为新链表进行反转,再与 fast 进行比较

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


struct ListNode* reverseList(struct ListNode* head){
    struct ListNode *cur = head;
    struct ListNode *pre = NULL;
    struct ListNode *next = NULL;

    while(cur != NULL)
    {
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }

    return pre;
}

bool isPalindrome(struct ListNode* head){
    if(head == NULL)
        return true;

    struct ListNode* fast = head;
    struct ListNode* slow = head;

    //while(fast->next != NULL && fast->next->next != NULL)
    while(fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
    }

    /* 
        nodes %2 == 1:
            1  2  3  2  1  NULL
                 <s>   <f>
            1  2  2  1  NULL
                 <s>    <f>
    */
    if(fast != NULL) // nodes %2 == 1
    {
        slow = slow->next;
    }
  
    slow = reverseList(slow);
  
    fast = head;

    //while(fast->next != NULL && slow->next != NULL)
    while(slow != NULL)
    {
        if(fast->val != slow->val)
            return false;

        fast = fast->next;
        slow = slow->next;
    }

    return true;
}

 

 查看更多刷题笔记

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值