- K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换
1.递推法
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//递推方法的使用
if(head == null) return head;
ListNode a, b;
a = b= head;
for(int i = 0; i < k; i++){//边界条件
if(b == null) return head;//如不足k个,则返回
b = b.next;
}
ListNode newHead = reverse(a, b);
a.next = reverseKGroup(b, k);
return newHead;
}
ListNode reverse(ListNode a, ListNode b){//反转[a,b)
//容易成环
ListNode n1, n2, n3;
n1 = a;
n2 = a.next;
n3 = null;
while (n2 != b){
n3 = n2.next;
n2.next = n1;
n1 = n2;
n2 = n3;
}
return n1;//返回头节点
}
ListNode reverse2(ListNode a, ListNode b){//反转[a,b)
ListNode n1, n2, n3;
if(a == null) return a;
n1 = null;//设置null
n2 = a;
n3 = null;
while(n2 != b){
n3 = n2.next;
n2.next = n1;
n1 = n2;
n2 = n3;
}
return n1;
}
}
2.迭代法
class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
//还是先指定一个暂时的头结点
ListNode head = new ListNode(-1);
ListNode cur = head;
for(int i = 0; i < n; i++){
int tmp = sc.nextInt();
cur.next = new ListNode(tmp);
cur = cur.next;
}
int k = sc.nextInt();
Solution ss = new Solution();
ListNode result = ss.reverseKGroup(head.next, k);
while (result != null){
System.out.print(result.val + " ");
result = result.next;
}
}
public ListNode reverseKGroup(ListNode head, int k) {
if(k < 2) return head;
ListNode pre = new ListNode(-1);
pre.next = head;//最终只需要返回pre.next;
ListNode last = pre;//last为上一单元的最后一个
int cnt = 1;
ListNode cur = head;//用来移动
ListNode save = null;
while(cur != null){//不能只使用一个变量cur,cur表示当前的最后一个节点,但是随着反转之后,cur就会变好,所以需要另一个变量先存储下一个节点
save = cur.next;//先存起来
if(cnt == k){
ListNode start = last.next;//该单元的第一个
ListNode end = cur;//该单元的最后一个
ListNode next = cur.next;//下一处理单元的第一个点,先保存下来
//内部反转,一个一个的来,不能直接使用start,end
ListNode n1 = start, n2 = n1.next;
while(n2 != next){
ListNode tmp = n2.next;//保存
n2.next = n1;
n1 = n2;
n2 = tmp;
}
//前后两段连接
last.next = end;
start.next = next;
last = start;//更新last,不用更新next
cnt = 0;
}
//cur = cur.next;
cur = save;//这里再往前走一步
cnt++;
}
return pre.next;
}
}