[leetcode] Palindrome Linked List

原题链接:https://leetcode.com/problems/swap-nodes-in-pairs/

我在github上的leetcode仓库是:https://github.com/cooljacket/leetcodes

问题

用O(n)的时间和O(1)的空间,判断一个单链表是否是回文的。

思路

先把前一半的链表反转,从中间开始往两边走,边走边判断

缺点

改变了链表的结构

solution

判断过后把结构恢复。

代码

首先贴一下简单的做法,不恢复链表的结构的:

class Solution {
public:
    // 思路:先把前一半的链表反转,从中间开始往两边走,边走边判断
    // 缺点:改变了链表的结构
    // solution:在判断的时候顺手把结构恢复
    bool isPalindrome(ListNode* head) {
        int len = getListLength(head);
        int halfSize = len >> 1, step = 0;
        ListNode *last = NULL;
        ListNode* rightHead = reverseList(head, last, halfSize);
        ListNode *leftHead = last;
        if (len % 2 != 0)
            rightHead = rightHead->next;

        while (leftHead != NULL) {
            if (leftHead->val != rightHead->val)
                return false;
            leftHead = leftHead->next;
            rightHead = rightHead->next;
        }

        return true;
    }

    // 遍历链表,计算其长度
    int getListLength(ListNode* head) {
        int len = 0;
        while (head != NULL) {
            ++len;
            head = head->next;
        }
        return len;
    }

    // 反转一段链表times步
    ListNode* reverseList(ListNode* head, ListNode*& last, int times) {
        ListNode *now = head, *tmp;
        int step = 0;
        while (step++ < times && now != NULL) {
            tmp = now->next;
            now->next = last;
            last = now;
            now = tmp;
        }
        return now;
    }
};

其实恢复就是对反转的那段链表,再反转一遍就好了!比如这样:

class Solution {
public:
    // 思路:先把前一半的链表反转,从中间开始往两边走,边走边判断
    // 缺点:改变了链表的结构
    // solution:在判断的时候顺手把结构恢复
    bool isPalindrome(ListNode* head) {
        int len = getListLength(head);
        int halfSize = len >> 1, step = 0;
        ListNode *last = NULL;
        ListNode* rightHead = reverseList(head, last, halfSize);
        ListNode *leftHead = last;
        ListNode *leftHeadCopy = leftHead, *rightHeadCopy = rightHead;
        if (len % 2 != 0)
            rightHead = rightHead->next;

        bool ans = true;
        while (leftHead != NULL) {
            if (leftHead->val != rightHead->val) {
                ans = false;
                break;
            }
            leftHead = leftHead->next;
            rightHead = rightHead->next;
        }

        // 最后,恢复链表的结构
        reverseList(leftHeadCopy, rightHeadCopy, halfSize);

        return ans;
    }

    // 遍历链表,计算其长度
    int getListLength(ListNode* head) {
        int len = 0;
        while (head != NULL) {
            ++len;
            head = head->next;
        }
        return len;
    }

    // 反转一段链表times步
    ListNode* reverseList(ListNode* head, ListNode*& last, int times) {
        ListNode *now = head, *tmp;
        int step = 0;
        while (step++ < times && now != NULL) {
            tmp = now->next;
            now->next = last;
            last = now;
            now = tmp;
        }
        return now;
    }
};

更多

其实一些小地方的运算,比如求长度的一般,可以直接除以2,但是用移位会更快!还有判断奇偶性,用模运算也是浪费,直接(x & 1) > 0,true就是奇数,false就是偶数。

这些操作在编译原理里边叫做”运算强度削弱“,如果追求效率的话,可以自己就这样做了,因为编译器不一定会帮你做好。同时注意注释,不然不懂的人可能看不太懂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值