234. Palindrome Linked List【力扣】

题意理解

判断一个链表是否是回文?

问题分析

链表问题,综合翻转+中间点

双指针找到链表中间点

后半链表翻转

前后半链表遍历比对是否相等

其他
链表是一个弱项。

双指针是常用的技巧。相差一个到两个的位置需要画图标记。

6.19:遍历链表,区分初始化,循环,结果判定三部分。做算法题不着急空手写代码,20分钟内都是正常水平,画图,手推都是好手段。

链接

        if(head == NULL || head -> next == NULL)
        {
            return true;
        }
        
        //快慢指针找中点
        ListNode *slow, *fast;
        slow = head;
        fast = head;
        while (fast -> next)
        {
            slow = slow -> next;
            fast = fast -> next -> next ? fast -> next -> next : fast -> next;
        }
        cout << "slow " << slow -> val << '\t' << "fast " << fast -> val << endl;
        //翻转后半部分
        //slow = slow -> next; //slow位置在中间或偏右的位置
        ListNode *p = slow -> next; //p插到slow前面
        slow -> next = NULL;
        while(p)
        {
            ListNode *q = p -> next;
            p -> next = slow; 
            slow = p;
            p = q;
        }
        p = slow;
        while(p)
        {
            cout << p -> val << '\t';
            p = p -> next;
        }
        cout << endl;
        cout << "slow " << slow -> val << '\t' << "fast " << fast -> val << endl;
        //比较前后半边链表
        while(head && slow)
        {
            if (head -> val != slow -> val)
            {
                return false;
            }
            head = head -> next;
            slow = slow -> next;
        }
        return true;

 

    bool isPalindrome(ListNode* head) {
        if (!head || !head -> next) //空链表 或 单结点链表
            return true;
        if (!head -> next -> next)
        {
            if (head -> next -> val == head -> val)
                return true;
            else
                return false;
        }
        ListNode* slow = head -> next;    //初始化第一次快,慢指针
        ListNode* fast = head -> next -> next;
        while(slow && fast)    //快慢指针存在
        {
            if (fast && fast -> next)   //快指针走两步
                fast = fast -> next -> next;
            else
                break;
            if (slow)   //慢指针走一步
                slow = slow -> next;
            else
                break;
        }
        cout << "slow " << slow -> val << endl;
        ListNode* rhHead = slow;    //保证遍历出来,slow指针指向后半部分头结点
        ListNode * p = rhHead;
        while (p)
        {
            cout << p -> val << '\t';
            p = p -> next;
        }
        ListNode* tail = rhHead;    //翻转链表的尾
        ListNode* curr = rhHead -> next;    //待处理结点
        while(curr)
        {
            tail -> next = curr -> next;    //尾指针接上后续结点
            curr -> next = rhHead;    //当前节点插入头结点前
            rhHead = curr;    //当前节点接管成为新头结点
            curr = tail -> next;    //新当前节点指向后续第一个结点
        }
        cout << "rh head " << rhHead -> val << endl;
        p = rhHead;
        while (p)
        {
            cout << p -> val << '\t';
            p = p -> next;
        }
        while (head && rhHead)    //前后半部分链表指针同时存在
        {
            cout << head -> val << "vs" << rhHead -> val << endl;
            if (head -> val != rhHead -> val)    //如果值不等
                return false;    //不是回文
            head = head -> next;    //下一步,指针后移
            rhHead = rhHead -> next;
        }
        return true;    //正常遍历完,说明是回文
        
    }

 

你可能感兴趣的:(算法,工作刷题,链表,C++)