做完这个题目,感觉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; }