想法一
先设置tail指针,在循环找尾的过程计数,最后得出节点数;再根据奇数和偶数判断,来找到中间节点
struct ListNode* middleNode(struct ListNode* head) { struct ListNode* tail = head; int count = 0;//节点数 while (tail) { tail = tail->next; count++; } int i = 0; if (count % 2 == 1) { for (i=0; i<(count-1)/2; i++) { head = head->next; } } else { for (i=0; i<count/2; i++) { head = head->next; } } return head; }
想法二
如果要求只遍历一遍链表的过程中,找到中间节点,又应该怎么做呢?
我们可以设置slow和fast两个指针,slow每次走一个节点,fast每次走两个节点,这样,当fast走到尾部时,slow就来到了中间节点(该方法比较考验思维)
struct ListNode* middleNode(struct ListNode* head) { //要求只遍历一遍链表 struct ListNode* slow = head;//一次走一格 struct ListNode* fast = head;//一次走两格 while (fast->next) { slow = slow->next; fast = fast->next->next; if (!fast) { break; } } return slow; }
注意:如果为偶数个节点时,fast会走到NULL,这时就要加上判断,提前跳出循环,防止对空指针进行解引用
以下是另一种表达方式,先判断fast是不是NULL,如果是,直接跳出循环,如果不是,才继续判断fast->next是不是NULL(&&的妙用)
struct ListNode* middleNode(struct ListNode* head) { //要求只遍历一遍链表 struct ListNode* slow = head;//一次走一格 struct ListNode* fast = head;//一次走两格 while (fast && fast->next) { slow = slow->next; fast = fast->next->next; } return slow; }