首页 > 代码库 > leetcode第一刷_Submission Details

leetcode第一刷_Submission Details

有段时间没更新了,专心刷了几天,差十几道结束,决定把第一季更完,然后按照我的理解分类再分析一遍,第二遍的时候应该会按照问题分类,应该会引用第一季的,如果想到或找到更好的解法,会更新第一季。

链表的问题就是恶心,思路大多直接,对指针的操作要非常小心。我自己常犯的错误主要有:

1. 在取val或者取next时,没有判空,造成Runtime Error。

2. 空指针和只有一个节点之类的边界情况。

3. 更新链表之后,没有将链表尾部置空,造成它指向其他的节点,构成环,或者想拆下链表的一部分时没有把那部分的尾部置空,构成环。

4. 同时用到多个指针时,平移,更新指针供下一个循环使用时,指针的更新顺序弄错了,造成了空指针或者环,出现TLE或者RE。

这道题还有点意思,第一个节点后面接的是最后一个,第二个接倒数第二个,我一开始看错题了,以为是从一半开始,第一个接第n/2个呢。不过思路差不多,这道题只要先找到一半的位置,把后面那部分链表反转一下,就可以同时用一个头指针和一个一半位置的指针更新了。

链表的O(N)和固定控件反转是解决很多链表问题的工具,而且很容易写错,应该多写几遍。我的写法很好理解,用三个指针。

下面是ac代码:

ListNode *reverse(ListNode *head){
    if(!head || !head->next)
        return head;
    ListNode *one = head, *two = head->next, *three = head->next->next;
    one->next = NULL;
    while(three){
        two->next = one;
        one = two;
        two = three;
        three = three->next;
    }
    two->next = one;
    return two;
}

class Solution {
public:
    void reorderList(ListNode *head) {
        if(!head || !head->next)
            return;
        int len=0;
        ListNode *pNode = head, *rpNode = head, *pre = NULL;
        while(pNode){
            len++;
            pNode = pNode->next;
        }
        if(len == 2)
            return;
        len = (len+1)/2;
        for(int i=0;i<len;i++){
            pre = rpNode;
            rpNode = rpNode->next;
        }
        if(pre)
            pre->next = NULL;
        rpNode = reverse(rpNode);
        ListNode *test = rpNode;
        pNode = head;
        while(rpNode){
            pre = rpNode->next;
            rpNode->next = pNode->next;
            pNode->next = rpNode;
            pNode = pNode->next->next;
            rpNode = pre;
        }
        return;
    }
};