做完这个题目,感觉LeetCode的题目出的真好。。。

这种题,如果让我在面试时候纸上写代码,肯定会挂的。

 

我昨天晚上看的题目,昨天脑子是懵的,放下了。今天早上来做。

 

一开始做,提交,果然错了。写的代码如下

struct ListNode * swap_2_nodes(struct ListNode *p)  //把p指向的两个节点交换位置
{
    struct ListNode * q;
    if( p == NULL || (q = p->next) == NULL )
    {
        return p;   //不够两个,就放弃转换了。
    }
    p->next = q->next;
    q->next = p;

    return q;
}
struct ListNode* swapPairs(struct ListNode* head) {
    int n = 0;
    struct ListNode * p,q;

    p = head;
    while(p!= NULL)
    {
        if( n%2 == 0)
        {
            p = swap_2_nodes(p);
            if(n==0)    head = p;
        }
        p = p->next;
        n ++;
    }
    return head;
}

 

这是潜意识里的错误。认为p是指向它的节点,那么p本身就是它前面的节点。这个太容易错了。。。

这个题目的结果就是  我把前两个1/2转换完,3和4确实也转换了,但是第二个节点1指向的仍然是3。也就是把后两个转换了,但是没有通报给前面。

也就是转换完之后,是这样

2->1->3    以及  4->3

很low的错误啊!

一直以为自己链表很熟练了,什么插入删除随便写。

现在看,问题多多啊!不能整天自我感觉良好。。。

 

归根结底:自己在思考问题的时候,总是偷懒!细节的地方不想去深究!没有搞非常明白,就开始编码。

比如 二分查找的边界。这种问题。

都是写出来,出错了,才根据错误来修改!

加油吧。。改变毛病很难。不改就没法提升。

 

附上正确答案,分循环和递归两种。

struct ListNode * swap_2_nodes(struct ListNode *p)  //把p指向的两个节点交换位置
{
    struct ListNode * q;
    if( p == NULL || (q = p->next) == NULL )
    {
        return p;   //不够两个,就放弃转换了。
    }
    p->next = q->next;
    q->next = p;
    
    return q;
}
struct ListNode* swapPairs(struct ListNode* head) {
    int n = 0;
    struct ListNode * p,q;
    
    head = swap_2_nodes(head);
    p = head;
    //唉!!!一定要记得前面一个节点还有用啊!! 转换3 和 4的时候,前面的2也要链接到啊!
    while(p!= NULL)
    {
        if( n%2 == 1)
        {
            p->next = swap_2_nodes(p->next);
        }
        p = p->next;
        n ++;
    }
    return head;
}

递归的可读性更强一些,而且思路非常清晰!

struct ListNode* swapPairs(struct ListNode* head) {
    
    struct ListNode * p;
    if(head == NULL || (p=head->next) == NULL)  return head;
    
    head ->next = swapPairs( p -> next);  //先把第三个开始的转换掉,然后用1的next指向他们。
    p->next = head;              //第2个指向1,然后返回2
    
    return p;
}

 

posted on 2017-11-29 09:30  newbird2017  阅读(132)  评论(0编辑  收藏  举报