题解一:迭代翻转
题解思路 : 建立一个空白节点指向头节点,然后翻转[m,n]内的节点。
参数分析: p:指向m前一个节点,q指向第n个节点。p1,p2用于翻转.
图示:
复杂度分析:
时间复杂度:O(N),最多遍历整个链表
空间复杂度:O(1),只使用了常数个变量
实现如下:
class Solution {
public:
/**
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
if(head==NULL||head->next==NULL||m==n) return head;
struct ListNode* p;
struct ListNode* q;
struct ListNode* l;
l = (struct ListNode*)malloc(sizeof(struct ListNode)); //创建空白节点
l->next = head; // 空白节点指向头节点
p = q = l;
for(int i =1;i<m;i++)
p = p->next; // p指向m前一个节点
for(int i = 1;i<=n;i++)
q = q->next; //q 指向第n个节点
struct ListNode* p1 = p->next; // p1 是第m个节点
struct ListNode* p2 = p1->next;
p->next = q; // m前一个节点要指向q
p1->next = q->next;
while(p2!=q){ //反转节点
p = p2->next;
p2->next = p1;
p1 = p2;
p2 = p;
}
p2->next = p1;
return l->next;
}
};题解二:递归
题解思路:利用反转链表的思想,使用递归
图示:反转链表的递归
递归分析:
递归边界:n=1 tmp保存子问题的部分的next用于拼接
递归进行: (m-1,n-1)表示反转开始的位置在子问题中的节点开始位置
图示:
复杂度分析:
时间复杂度:O(N)
空间复杂度:O(N),最坏递归栈深度
实现如下:
class Solution {
public:
ListNode* tmp = NULL;
ListNode* reverseBetween(ListNode* head, int m,int n){
if( m == 1) return reverse(head, n);
ListNode* p = reverseBetween(head->next, m-1,n-1); // m,n在子问题中要减1
head->next = p; //拼接反转之后的部分
return head;
}
ListNode* reverse(ListNode* head,int n){
if(n == 1){
tmp = head->next;
return head;
}
ListNode* new_head = reverse(head->next,n-1); //子问题,位置要减1
head->next->next = head; //反转
head->next = tmp; //拼接尾部
return new_head;
}
};
京公网安备 11010502036488号