题目描述
链表每k个节点之间逆序,最后不足k个的节点不用逆序。
解题方法1
- 最简便的方式可以使用栈来完成,将链表节点依次入栈,当栈中元素达到k个时再依次出栈尾插到新链表中,这样不断入栈k个元素出栈k个元素就可以实现每k个节点之间逆序。
- 需要注意的是,如果链表长度不是k的倍数,会有最后一组节点不足k个。如果循环结束栈中还有元素就将这些元素按原链表顺序插入到新链表之后(头插)。
public class Test {
public static void main(String[] args) throws Exception {
int[] arr = {1,2,3,4,5,6,7,8,9,10,11,12};
Node head = create1(arr);
fun(head,3);
for(Node p=head.next;p!=null;p=p.next){
System.out.println(p.val);
}
}
//将单链表每k个节点逆序
public static void fun(Node head,int k){
Stack<Node> s = new Stack<>();
Node p = head.next;
Node last = head;
last.next = null;
while(p!=null){
while(s.size()<k &&p!=null){
s.push(p);
System.out.println("push:"+p.val);
p=p.next;
}
if(s.size()==k){ //只有当前栈中元素为k才进行逆置操作
while(!s.empty()){
Node newnode = s.pop();
System.out.println("pop:"+newnode.val);
newnode.next = last.next;
last.next = newnode;
last = newnode;
}
}
}
//如果栈中还有元素,不需要逆置 所以基于last节点进行头插
while(!s.empty()){
Node newnode = s.pop();
newnode.next = last.next;
last.next = newnode;
}
}
//创建一个无环单链表
public static Node create1(int[] arr){
Node head = new Node(0); //头节点
Node newnode = null; //指向新节点
Node lastnode = head; //指向链表尾节点
for(int a:arr){
newnode = new Node(a); //创建新节点
newnode.next = lastnode.next; //尾插核心操作
lastnode.next = newnode;
lastnode = newnode; //迭代指针
}
return head;
}
}
class Node{
int val;
Node next;
Node(int val){
this.val = val;
}
}
解题方法2
- 上述解法需要k的空间复杂度。我们可以进行优化,使用一个计数器找到每一组的首尾节点,以及当前组的上一个和下一个节点,然后逐组进行逆序,每逆序一个组将当前组与上一个和下一个节点进行连接。
- 比如 链表:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14,k = 4。(0为头节点)
- 则:第一组:
上一个节点 0
首节点 1
尾节点 4
下一个节点 5
- 第二组:
上一个节点 1(逆序后1变成第一组最后一个节点)
首节点 5
尾节点 8
下一个节点 9
- 第三组:
上一个节点 5
首节点 9
尾节点 12
下一个节点 13
- 比如当前得到第一组的 0 1 4 5,我们先基于节点0进行头插操作,依次将1 2 3 4头插到0节点之后,此时1变成尾节点,再将1指向下一个节点5即可。
public class Test {
public static void main(String[] args) throws Exception {
int[] arr = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
Node head = create1(arr);
fun(head,4);
for(Node p=head.next;p!=null;p=p.next){
System.out.print(p.val + " ");
}
}
//将单链表每k个节点逆序 {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
public static void fun(Node head,int k){
if(head.next==null || k<2){
return;
}
Node p = head.next;
Node left = head; //指向当前组的上一个节点
Node start = head.next; //指向当前组的开始节点
Node end = null; //指向当前组的尾节点
Node right = null; //指向最后一组的下一个节点
int count = 1;
while(p!=null){
Node temp=p.next;
if(count==k){
end = p; //更新当前组end值
right = end.next; //更新最后一组下一个节点
//逆序 start到end之间的节点
reverse(left,start,end,right);
left = start; //下一组上一个节点就是当前组第一个节点
start = temp; //下一组start值就是节点p的下一个节点
count=0;
}
p=temp;
count++;
}
}
//传入当前组上一个节点,当前组首尾节点 进行逆序操作
public static void reverse(Node left,Node start,Node end,Node right){
System.out.println("上一个"+left.val);
System.out.println("首节点"+start.val);
System.out.println("尾节点"+end.val);
System.out.println("下一个"+end.next.val);
left.next = null; //基于left进行头插要先将left指向null
Node p=start;
while(p!=right){
Node temp = p.next;
p.next = left.next;
left.next = p;
p = temp;
}
start.next = right; //将逆序后当前组最后一个节点指向下一组第一个节点 这条语句用于连接原链表最后不足k个的节点
}
//创建一个单链表
public static Node create1(int[] arr){
Node head = new Node(0); //头节点
Node newnode = null; //指向新节点
Node lastnode = head; //指向链表尾节点
for(int a:arr){
newnode = new Node(a); //创建新节点
newnode.next = lastnode.next; //尾插核心操作
lastnode.next = newnode;
lastnode = newnode; //迭代指针
}
return head;
}
}
class Node{
int val;
Node next;
Node(int val){
this.val = val;
}
}
来源:CSDN
作者:zuiziyoudexiao
链接:https://blog.csdn.net/zuiziyoudexiao/article/details/104576119