1. 问题描述
问题主要就是将链表从m,n翻转其中的节点,包含m和n这个节点
1<=m<=n<=head.length
1->2->3->4->5->NULL m=2,n=4 即反转m与n之间的链表
1->4->3->2->5->NULL
2. 思路
2.1 思路1
思路1的话主要是找到m,然后遍历找到n,然后翻转m-n之间的节点,然后将前后拼接起来即可
public ListNode reverseBetweenII(ListNode head, int m, int n) {
if (head == null || head.next == null) return head;
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
int cnt = 0;
ListNode pre = dummyNode;// 设置虚拟节点
ListNode cur = pre.next;// 设置头节点
while (cur != null) {
cnt += 1;
if (cnt == m) {// 找到第一个节点
ListNode t = cur;// 记录下来拼接尾节点的前一个节点
while (cnt != n) {
cnt += 1;
cur = cur.next;
}
// temp作为尾节点
ListNode temp = cur.next;
cur.next = null;// 切断联系
ListNode node1 = pre.next;// 记录需要翻转的部分
pre.next = null;// 切断联系
pre.next = reverseNode(node1);// 翻转,然后头节点拼接上
t.next = temp;// 尾节点拼接,返回即可
return dummyNode.next;
}
cur = cur.next;
pre = pre.next;
}
return null;
}
private ListNode reverseNode(ListNode head) {
if (head == null) return null;
if (head.next == null) return head;
ListNode p = reverseNode(head.next);// 一直遍历找最后一个
head.next.next = head;// 通过修改空间中的指针指向,这里实质修改了节点与p的关系
head.next = null;// 切点head节点的联系
return p;
} 2.2 思路2
思路2的话主要是通过递归的方法来,如果是从m=1开始翻转,则直接返回翻转后的。这里的翻转是记录尾节点即tailNode,然后再中途修改head指针与node指针之间的关系,从而实现链表翻转。如果是画图的话,可以看到,所有的节点其实就是从节点的上一个节点插入到tailNode前面,从而维持相对的关系。
ListNode tailNode = null;
public ListNode reverseBetween(ListNode head, int m, int n) {
if (m == 1) {
// 如果是第一个节点开始,全都翻转
return reverseN(head, n);
}
// 因为翻转的是相对大小位置,所以m-1,则n-1,需要对应变化才奏效
head.next = reverseBetween(head.next, m - 1, n - 1);
return head;
}
private ListNode reverseN(ListNode head, int n) {
// 获取到尾节点,就是为了待会连接的问题
if (n == 1) {
tailNode = head.next;// 保留尾部节点
return head;
}
// 递归向后走
ListNode node = reverseN(head.next, n - 1);
// 改变节点与node的指向
head.next.next = head;
// 实质就是往靠近tailNode的位置插入
head.next = tailNode;
// 返回node
return node;
} 3. 小结
这道题之前也做过,但是许久不做又生疏了,但是如果做也可以做出来。只是链表的转向真的比较有趣。如果不熟悉最好打断点,然后画图,还是比较简单的。
Keep thinking, keep coding! 加油
2020-08-25写于深圳南山

京公网安备 11010502036488号