将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度
,空间复杂度
。
例如:
给出的链表为
,
,
返回
.
例如:
给出的链表为
返回
数据范围: 链表长度
,
,链表中每个节点的值满足
要求:时间复杂度
,空间复杂度
进阶:时间复杂度
,空间复杂度
{1,2,3,4,5},2,4{1,4,3,2,5}{5},1,1{5}
{1,2,3,4},1,4{4,3,2,1}import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
if (head == null || head.next == null || m == n) {
return head;
}
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
ListNode cur = head;
ListNode nxt = null;
for (int i = 0; i < m - 1; i++) {
pre = pre.next;
}
cur = pre.next;
if (cur == null || cur.next == null) {
return head;
}
ListNode grouppre = null;
ListNode grouphead = cur;
for (int i = m; i <= n; i++) {
nxt = cur.next;
cur.next = grouppre;
grouppre = cur;
cur = nxt;
}
grouphead.next = cur;
pre.next = grouppre;
return dummy.next;
}
} import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
//如果链表为空,直接返回空
if (head == null) {
return null;
}
//如果 m == n,说明不需要反转,直接返回原链表
else if (m == n) {
return head;
}
//创建一个虚拟头节点 pre,用于处理从头开始反转的情况(比如 m=1)
//p1 是 pre 的指针,用来遍历找到第 m - 1 个节点的位置
else {
ListNode pre = new ListNode(0), p1 = pre;
pre.next = head;
//将 p1 指到第 m - 1 个节点,此时:
//p1.next 就是需要开始反转的第一个节点(即第 m 个节点)
for (int i = 1; i < m; i++) {
p1 = p1.next;
}
//p2 指向当前要反转的起始节点(即第 m 个节点)
//temp 记录操作前的节点数据,后续用于连接后半段链表
ListNode p2 = p1.next, temp = p1.next;
//使用“头插法”,把 p2 所在的节点依次插入到 p1 后面,从而实现局部反转
for (int j = m; j <= n; j++) {
//node = p2.next: 保存下一个要反转的节点
ListNode node = p2.next;
//p2.next = p1.next: 当前节点插入到 p1 后面
p2.next = p1.next;
//p1.next = p2: 插入完成
p1.next = p2;
//p2 = node: 继续处理下一个节点
p2 = node;
}
//将原来的第一个反转节点(temp)指向 p2,也就是反转后的剩余部分
temp.next = p2;
//返回 pre.next,确保即使头节点被反转了也能正确返回新头节点
return pre.next;
}
}
} import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
ListNode[] nodes = new ListNode[n+1];
List<ListNode> list = new ArrayList<>();
int loc=1;
while(head != null) {
if(loc<m) {
nodes[loc] = head;
} else if(loc>=m && loc<=n) {
nodes[n-(loc-m)] = head;
} else {
list.add(head);
}
head = head.next;
loc++;
}
head = new ListNode(-1);
ListNode r = head;
for(int i=1; i<=n; i++) {
System.out.println(nodes[i].val);
r.next = nodes[i];
r = r.next;
}
for(int i=0; i<list.size(); i++) {
System.out.println(list.get(i).val);
r.next = list.get(i);
r = r.next;
}
r.next = null;
return head.next;
}
} public class Solution {
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
if (m == n) {
return head;
}
ListNode temp = head;
List<ListNode> cache = new ArrayList<>(n-m+1);
int sign = 1;
while(head!=null){
if(sign>=m&&sign<=n){
cache.add(head);
}
head= head.next;
sign++;
}
int left = 0;
int right = cache.size()-1;
while(left<right){
ListNode leftNode = cache.get(left);
ListNode rightNode = cache.get(right);
int leftTemp = leftNode.val;
leftNode.val = rightNode.val;
rightNode.val = leftTemp;
left++;
right--;
}
return temp;
}
} 利用栈
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
Stack stack = new Stack();
ListNode temp = new ListNode(0);
ListNode temp1 = temp;
int count = 1;
while (head != null) {
if (count >= m && count <= n) {
stack.push(head);
} else {
if (stack.isEmpty()) {
temp.next = head;
temp = head;
} else {
while (!stack.isEmpty()) {
ListNode pop = stack.pop();
temp.next = pop;
temp = pop;
}
temp.next = head;
temp = head;
}
}
count++;
head = head.next;
}
if (!stack.isEmpty()) {
while (!stack.isEmpty()) {
ListNode pop = stack.pop();
temp.next = pop;
temp = pop;
}
temp.next = null;
}
return temp1.next;
}
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
// 1.先定义两个指针start和end,分别指向前方的m位置和后方的n位置
ListNode start = null;
ListNode end = null;
// 2.记录start指针的上一个结点allPre,end指针的下一个结点allPost
ListNode allPre = head; // 先把allPre指向head这个整个链表的起点,随着查找m可以往后移动head
ListNode allPost = null;
// 准备找到m和n位置对应的start和end,以及对应的allPre和allPost
ListNode cur = head;
for (int i = 1; cur != null; cur = cur.next, i++) {
if (i == m) {
start = cur;
}
if (i == n) {
end = cur;
allPost = end.next;
break;
}
// 只有在i>1(让allPre落后一位)且i<m(还没找到start)时更新allPre
if (i > 1 && i < m) {
allPre = allPre.next;
}
}
System.out.println("allPre: " + (allPre != null ? allPre.val : "null"));
System.out.println("start: " + (start != null ? start.val : "null"));
System.out.println("end: " + (end != null ? end.val : "null"));
System.out.println("allPost: " + (allPost != null ? allPost.val : "null"));
// 3.执行类似于上一题的方法,反转start和end之间的链表,返回反转后的起点newStart和终点newEnd
ListNode newStart = end;
ListNode newEnd = start;
// 只有strat和end不指向同一个结点(反转区间>1)时,才有反转的必要
if (start != end) {
ListNode newPre = start;
ListNode newCur = start.next;
ListNode newNext = newCur.next;
// 此处不用管newPre的next指向何方,因为这个newPre就是newEnd,是数组反转后的结尾,下文会令其指向allPost
while(newCur != allPost) {
newNext = newCur.next;
newCur.next = newPre;
System.out.println("结点" + newCur.val + "的反转已完成");
newPre = newCur;
newCur = newNext;
}
}
// 4.令allPre指向newStart,令allPost指向newEnd
// 注意allPre的边界判断!allPre可能与newEnd(start)重合!
if (allPre == newEnd) {
// 如果allPre 跟 newEnd(start) 是同一个结点(m=1的情况),说明start前面没有任何元素,这时可以直接移动head到链表区间反转后的起点,令head = newStart
allPre = newStart;
head = allPre;
} else {
// 否则,是正常情况,令allPre指向newStart,从newStart到newEnd是反转区间
allPre.next = newStart;
}
newEnd.next = allPost;
System.out.println("newEnd结点" + newEnd.val + "的下一个结点allPost是" + (allPost != null ? allPost.val : "null"));
System.out.println("allPre结点" + allPre.val + "的下一个结点newStart是" + (newStart != null ? newStart.val : "null"));
System.out.println("head结点" + head.val);
return head;
}
} public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
ListNode pre=new ListNode(0) ,p1=pre;
pre.next=head;
for(int i=1;i<m;i++){
p1=p1.next;
}
ListNode p2=p1.next ,temp=p1.next;
for(int i=m;i<=n;i++){
ListNode node=p2.next;
p2.next=p1.next;
p1.next=p2;
p2=node;
}
temp.next=p2;
return pre.next;
} public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
if (head == null || m >= n) {
return head;
}
ListNode rootNode = new ListNode(0);
rootNode.next = head;
ListNode pre = null;
ListNode mNode = null;
ListNode nNode = null;
ListNode mmNode = null;
int k = 1;
int j = 0;
while(k <= n && head!= null){
if (k+1 == m){
mNode = head;
mmNode = head.next;
j++;
}else if(k == m && j == 0){
mNode = rootNode;
mmNode = head;
}
if (k == n){
nNode = head.next;
}
if (k >= m && k <= n){
ListNode temp = head.next;
head.next = pre;
pre = head;
head = temp;
}else{
head = head.next;
}
k++;
}
mNode.next = pre;
mmNode.next = nNode;
return rootNode.next; // 返回链表的头节点
} 为解题而解题硬凑的,算法还是Java排第一的那个妙 import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
ListNode tmp = head;
ListNode pre, cur, preNode = null, tailNode = null;
int i = 0;
//范围包含头结点,则创建一个结点使得 next 域指向 head
if (m == 1) {
preNode = new ListNode(0);
preNode.next = head;
}
//遍历链表找到起始节点
while (tmp != null) {
//若范围不包含头节点,则记录范围两头相邻的节点preNode、tailNode
if (i == m - 2) {
preNode = tmp;
}
if (i == n) {
tailNode = tmp;
}
tmp = tmp.next;
i++;
}
pre = null;
cur = preNode.next;
//反转链表
while (cur != null) {
if (cur == preNode.next) {
pre = tailNode;
}
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
if (cur == tailNode) {
preNode.next = pre;
break;
}
}
if (m == 1) {
return preNode.next;
}
return head;
}
}