描述
给你一个链表,请你两两交换相邻节点,你需要真正交换节点本身,而不是修改节点的值。
两两交换示例:
链表 :1->2->3->4 交换后 :2->1->4->3
链表 :1->2->3 交换后: 2->1->3
数据范围:链表长度满足 , 链表上的值满足
问题分析: 两两交换节点,其实跟链表k个一组翻转类似。只不过这里的k=2.那么我们就不需要编写反转链表函数。也没必要采用反转的方法来做。
记录一个当前需要交换位置的前驱pre, 假设当前位置为head,开始进行操作前,再记录一个后驱p=head->next->next,
然后做下面的操作:pre->next=head->next,pre->next->next=head,head->next=p,pre=head(作为新的前驱),head=head->next。
具体过程看下面代码:
复杂度分析:
时间复杂度O(n):整个过程只需要遍历一遍链表就完成了。
空间复杂度O(1):只定义了一个指针和新创建了一个节点。
/** * struct ListNode { * int val; * struct ListNode *next; * ListNode(int x) : val(x), next(nullptr) {} * }; */ class Solution { public: ListNode* swapLinkedPair(ListNode* head) { if(head==NULL||head->next==NULL) return head; //因为头节点没有前驱,所以需要创建一个新节点 ListNode *Nhead=(ListNode*)malloc(sizeof(ListNode)); Nhead->next=head; ListNode *p,*pre; pre=Nhead; while(head->next!=NULL&&head!=NULL) { //因为下面操作会改变指针指向,所以需要用p提前记录下一个需要交换的位置 p=head->next->next; pre->next=head->next; pre->next->next=head; head->next=p; pre=head;//作为下一个需要交换的前驱 head=head->next; } return Nhead->next; } };