两两交换链表的节点
题意
给一个链表,两个两个的实际的交换节点
方法
每两个一处理
分析
既然是两两交换,那么当我们把前两个处理完以后,后面剩余的部分可以递归用同样的方法处理
所以每次把第二个作为新的根,指向第一个节点
而第一个节点指向 递归后面的节点
代码
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* swapLinkedPair(ListNode* head) {
if(head == NULL)return NULL; // 本身是空
if(head->next == NULL) return head; // 奇数个
// head r r1 => r head r1
ListNode* r = head->next; // 新的根
ListNode* r1 = head->next->next; // 三个往后
r->next = head; // 指向第一个
head->next = swapLinkedPair(r1); // 第一个指向递归
return r;
}
};
复杂度分析
空间复杂度: 主要和递归深度相关,空间复杂度为
时间复杂度: 对于每两个节点,操作代价为常数,所以总时间复杂度为
转换成数组再处理
分析
先把链表转换成数组
再两两一对改造指向每个
对于每两个一组,后一个直接指向前一个,而前一个应该指向下一组的起始,根据下一组个数是0,1,2处理各不相同
最后输出链,也需要注意根据节点是1个还是大于1个起始点有不同
样例
以样例数据为例
代码
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* swapLinkedPair(ListNode* head) {
if(head == NULL)return NULL;
vector<ListNode*> nodes; // 转化成数组
ListNode* p = head;
while(p){
nodes.push_back(p);
p = p->next;
}
for(int i = 0;i < nodes.size();i++){
if(i%2 == 0){ // 两个一组的前一个
if(i + 3 < nodes.size()){ // 后面有不少于2个点
nodes[i]-> next = nodes[i+3];
}else if(i + 2 < nodes.size()){ // 后面仅有一个点
nodes[i]-> next = nodes[i+2];
}else{ // 这就是结尾
nodes[i]-> next = NULL;
}
}else{ // 两个一组的后一个
nodes[i] -> next = nodes[i-1];
}
}
return nodes.size() > 1 ? nodes[1]:nodes[0]; // 起始节点不同
}
};
复杂度分析
空间复杂度: 主要消耗在转化出的数组,空间复杂度为
时间复杂度: 对于每个节点操作代价为常数,所以总时间复杂度为