题目:
将head单链表以m为组反转链表(不足m则不反转):
例子:假设m=3. 链表 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 ->8
output: 3 -> 2 -> 1 ->6 ->5 ->4 -> 7 ->8
思路:
可以使用栈的结构解决这个问题,如果栈中值为K则弹出栈
使用栈的结构,时间复杂度O(n),控件复杂度为O(K)
1.代码如下:
1.1Node.java
package com.yuhl.right.node;
/**
* @author yuhl
* @Date 2020/10/24 15:36
* @Classname Node
* @Description TODO
*/
public class Node {
private int value;
private Node next;
public Node() {
}
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
1.1NoteTest.java
package com.yuhl.right.node;
import com.yuhl.Main;
import java.util.Stack;
/**
* @author yuhl
* @Date 2020/10/24 15:38
* @Classname NoteTest
* @Description
*
* 将head单链表以m为组反转链表(不足m则不反转):
* 例子:假设m=3. 链表 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 ->8
* output: 3 -> 2 -> 1 ->6 ->5 ->4 -> 7 ->8
*/
public class NoteTest {
public static void main(String[] args) {
//构建单链表
Node node8 = new Node(8, null);
Node node7 = new Node(7, node8);
Node node6 = new Node(6, node7);
Node node5 = new Node(5, node6);
Node node4 = new Node(4, node5);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node node1 = new Node(1, node2);
Node nodeRev = getRevNode(node1,3);//获取旋转之后的链表
printLinck(nodeRev, 8);//打印旋转之后的链表
}
/**
* 使用栈的结构,时间复杂度O(n),控件复杂度为O(K)
* @param head 头结点
* @param K 每K个为一组
* @return 新的头结点
*
*/
private static Node getRevNode(Node head, int K) {
if (K < 2) {//如果仅有一个结点就返回当前头结点
return head;
}
//栈中存放K个节点
Stack<Node> stack = new Stack<>();
Node newHead = head;//新的头结点,返回值用
int count = 1;//计数,每到K则重置为1
Node cur = head;//当前节点
Node pre = null;//前一个节点
Node next = null;//后一个节点
while (cur != null) {
next = cur.getNext();
stack.push(cur);
if (stack.size() == K) {
pre = pesign1(stack, pre, next);
newHead = newHead == head ? cur : newHead;//如果第一次进来newHead == head 取cur节点,要不然取newHead说明已经赋值过了。
}
cur = next;
}
return newHead;
}
private static Node pesign1(Stack<Node> stack, Node left, Node right) {
Node cur = stack .pop();
if (left != null) {
left.setNext(cur);
}
Node next = null;
while (!stack.isEmpty()) {
next = stack.pop();
cur.setNext(next);
cur = next;
}
cur.setNext(right);
return cur;
}
private static void printLinck(Node nodeRev, int len) {
Node noteTem = nodeRev;
for (int i = 0; i < len; i++) {
if (i == len - 1) {//最后的一个结点后面无须->
System.out.print(noteTem.getValue());
} else {
System.out.print(noteTem.getValue() + "->");
}
noteTem = noteTem.getNext();
}
}
}
2.运行结果如下:
"C:\Program Files\Java\jdk1.8.0_201\bin\java.exe"
3->2->1->6->5->4->7->8
3.运行结果如下:
更容易理解的方式写代码:
3.1 Node.java
package com.yuhl.test001.revNode;
/**
* @author yuhl
* @Date 2020/10/31 11:20
* @Classname Node
* @Description 链表选装的Node类
*/
public class Node {
public int value;
public Node next;
public Node() {
}
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
}
3.2 RevNodeTest.java
package com.yuhl.test001.revNode;
import com.yuhl.right.tree1.TreeNodeTest2;
import java.util.Stack;
/**
* @author yuhl
* @Date 2020/10/31 11:21
* @Classname RevNodeTest
* @Description 算法002:将单链表的每K个节点之间逆序,例子:假设m=3. 链表 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 ->8 output: 3 -> 2 -> 1 ->6 -.
* 旋转的方法,入栈会简单很多。
*/
public class RevNodeTest {
public static void main(String[] args) {
//构建单链表
Node node8 = new Node(8, null);
Node node7 = new Node(7, node8);
Node node6 = new Node(6, node7);
Node node5 = new Node(5, node6);
Node node4 = new Node(4, node5);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node head = new Node(1, node2);
Node newHead = revNode(head, 4);
printnewHead(newHead);
}
//打印链表
private static void printnewHead(Node newHead) {
Node tmpNode = newHead;
while (true) {
if (tmpNode != null) {
System.out.print(tmpNode.value+ " ");
if (tmpNode.next != null) {
tmpNode = tmpNode.next;
} else {
break;
}
}
}
}
public static Node revNode(Node head,int len){
if (head.next == null || len <= 1) {//如果只有一个结点,则直接返回
return head;
}
Node newHead = null;//返回的新的链表的头部
Node curNode = head;//临时节点,入栈使用
Node tmpNode = null;//临时节点: 出栈使用
Node preNode = null;//N 个节点的最后一个,用于N+1个节点往前连接
Node noRevNode = null;//记录每次入栈的第一个,有可能是不逊转的。
Node preNodeSer = null;//弹出stack时的前置节点
//入栈
Stack<Node> stack = new Stack();
int flag = 1;//为1:可以旋转,0为不可以旋转,不足len
while(flag == 1){
//入栈
for (int i = 1; i <= len; i++) {
if(i == 1){
noRevNode = curNode;
}
stack.push(curNode);
if (curNode.next != null) {
curNode = curNode.next;
} else {
//把n的最后一个结点接在现在的节点上。
flag = 0; //可以旋转,
break;//不足len,不旋转
}
}
//出栈
if (stack.size() == len) { //旋转
for (int i = 1; i <= len; i++) {
Node popNode = stack.pop();
tmpNode = popNode;
if (newHead == null) {//第一次弹出,就是新的首节点,要不然首节点已经被占说明是>1次的弹出
newHead = popNode;
preNodeSer = popNode;
} else {
preNodeSer.next = tmpNode;
preNodeSer = tmpNode;
if(i == len){//记录下次节点需要连上的上次的节点
preNode = popNode;// preNode = tmpNode;
if (0 == flag) {
preNode.next = null;//要不然会循环打印
}
}
}
}
} else {//不旋转
if (newHead == null) {//如果len>size时使用
return head;
}
preNode.next = noRevNode;
}
if (tmpNode.next == null) {
flag = 0;
}
}
return newHead;
}
}
3.3 运行结果
4 3 2 1 8 7 6 5