链表算法题(程序员面试宝典)
解题思路主要来源于leetcode官方与《程序员面试宝典》。
25. K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
解题方法
解题思路1
利用栈的先进先出的特性,来反转链表。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//利用栈先进后出的特性来反转
Stack<ListNode> nodeStack = new Stack<ListNode>();
//反转后的新链表头
ListNode newHead = new ListNode(-1);
newHead.next = head;
//新链表的尾指针
ListNode taileNode = newHead;
while(true){
ListNode tempNode = head;
//结束条件,链表为空
if(tempNode==null){
//解决链表循环问题
taileNode.next = null;
break;
}
//将K个节点压入栈中
int count = 0;
while(tempNode!=null&&count<k){
nodeStack.push(tempNode);
tempNode = tempNode.next;
count++;
}
//结束条件,当栈中节点不足k个时,则推出翻转操作
if(count<k){
taileNode.next = head;
break;
}
//当栈中不为空时,弹出栈中元素尾插至新链表
while(!nodeStack.empty()){
ListNode node = nodeStack.pop();
taileNode.next = node;
taileNode = taileNode.next;
}
//更新head
head = tempNode;
}
return newHead.next;
}
}
解题思路2
头插法的思想反转链表。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//为链表添加空头节点
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode preNode = dummy;
ListNode tailNode = dummy;
while(true){
//先找到要反转节点的尾
int count = 0;
while(tailNode!=null&&count<k){
tailNode = tailNode.next;
count++;
}
if(tailNode==null){
break;
}
//头插法反转链表
ListNode newHead = preNode.next;
while(preNode.next!=tailNode){
//先取preNode的后继节点
ListNode curNode = preNode.next;
//先更新preNode 的后继节点
preNode.next = curNode.next;
//将curNode 以头插法插到tailNode之后
curNode.next = tailNode.next;
tailNode.next = curNode;
}
//更新preNode tailNode
preNode = newHead;
tailNode = newHead;
}
return dummy.next;
}
}
解题思路3
递归思想。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//递归思想
ListNode curNode = head;
int count=0;
while(curNode!=null&&count<k){
curNode = curNode.next;
count++;
}
if(count==k){
curNode = reverseKGroup(curNode,k);
while(count!=0){
count--;
//反转指针来反转链表
ListNode tempNode = head.next;
//反转指针
head.next = curNode;
//更新curNode,head
curNode = head;
head = tempNode;
}
return curNode;
}
return head;
}
}