方法1: 改变数据结构-转数组
方法2: 双指针
- 先把指定区间给找出来,按照正常链表进行反转
- 将已经反转好的局部链表与其他节点建立连接,重构链表.如下图,图非原创。
function reverseLinkedList(head) {
let pre = null;
let cur = head;
while(cur!=null){
//Cur_next 指向cur节点的下一个节点
const Cur_next = cur.next;
cur.next = pre;
pre = cur;
cur = Cur_next ;
}
}
function reverseBetween( head , m , n ) {
//设置虚拟头节点
let dummyNode = new ListNode(-1);
dummyNode.next = head;
//1.走left-1步,获取到left的前一个节点
let pre = dummyNode;
for(let i=0;i<m-1;i++){
pre = pre.next;
}
//2. 走到right节点
let rigthNode = pre;
for(let i=0;i<n-m+1;i++){
rigthNode = rigthNode.next;
}
//3.截取出要反转的链表
let leftNode = pre.next;
let cur = rigthNode.next; // 右节点的下个节点
//4.切断链接
pre.next=null; // 切断左节点
rigthNode.next=null; // 切断右节点
//5.反转局部链表
reverseLinkedList(leftNode);
//6.接回原来的链表
pre.next = rigthNode;
leftNode.next = cur;
return dummyNode.next;
}
时间复杂度:O(N) N是链表总节点数。最坏情况下,需要遍历整个链表 空间复杂度:O(1) 仅使用到常数个变量
方法3: 原地反转 如下图,将5插入到2前面,再将4插入到5前面,依次循环。
function reverseBetween( head , m , n ) {
let dummyNode = new ListNode(-1);
dummyNode.next =head;
let pre = dummyNode; // 左节点的前一个节点 上图中就是7
for(let i=0;i<m-1;i++){
pre = pre.next;
}
let cur = pre.next; // 2
let Cur_next;
for(let i=0;i<n-m;i++){
Cur_next = cur.next; // 暂存旧的下个节点,图中是5
cur.next = Cur_next.next; // 2指向4【5的下个节点】
Cur_next.next = pre.next; // 5指向2
pre.next = Cur_next; // 7指向5
}
return dummyNode.next;
}
复杂度分析:
时间复杂度:O(N) 其中 N是链表总节点数。最多只遍历了链表一次,就完成了反转 空间复杂度O(1) 仅使用到常数个变量