链表反转算法

闲余时间把看了一些常见的算法题,把链表对应的常见算法写了一下 如有疑问可加我QQ:1051980588共同探讨

  1 package com.trs.codetool.sort;
  2 
  3 /**
  4  * @author zheng.changgang
  5  * @date 2020-01-02 09:57
  6  * 链表的常见算法
  7  */
  8 public class LianBiao {
  9     static Node  head = new Node(0);
 10     public static void main(String[] args) {
 11         int[] nums = {1,2,3,4,5};
 12         for(int i=0;i<nums.length;i++) {
 13             addNode(nums[i]);
 14         }
 15         //printNode(head);
 16 
 17      /*  // 递归反转链表
 18         Node invertNode = invertLinkedList(head.next);
 19         System.out.println();
 20         head.next = invertNode;
 21         printNode(head);
 22         // 非递归反转链表
 23         iterationInvertLinkedList(head);
 24         printNode(head);
 25         Integer from = 2;
 26         Integer to = 4;
 27         // 变形题 1:给定一个链表的头结点 head,以及两个整数 from 和 to ,在链表上把第 from 个节点和第 to 个节点这一部分进行翻转。例如:给定如下链表,from = 2, to = 4 head-->5-->4-->3-->2-->1 将其翻转后,链表变成 head-->5--->2-->3-->4-->1
 28         iterationInvertLinkedList(head,from,to);
 29         printNode(head);**/
 30        // 变形题 2:给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序
 31         iterationInvertLinkedListEveryK(2);
 32         printNode(head);
 33 
 34     }
 35 
 36     /**
 37      * 每 k 个一组翻转链表
 38      * @param k
 39      */
 40     public static void iterationInvertLinkedListEveryK(int k) {
 41         Node tmp = head.next;
 42         int step = 0;               // 计数,用来找出首结点和尾结点
 43 
 44         Node startK = null;         // k个一组链表中的头结点
 45         Node startKPre = head;      // k个一组链表头结点的前置结点
 46         Node endK;                  // k个一组链表中的尾结点
 47         while (tmp != null) {
 48             // tmp 的下一个节点,因为由于翻转,tmp 的后继结点会变,要提前保存
 49             Node tmpNext = tmp.next;
 50             if (step == 0) {
 51                 // k 个一组链表区间的头结点
 52                 startK = tmp;
 53                 step++;
 54             } else if (step == k-1) {
 55                 // 此时找到了 k 个一组链表区间的尾结点(endK),对这段链表用迭代进行翻转
 56                 endK = tmp;
 57                 Node pre = null;
 58                 Node cur = startK;
 59                 if (cur == null) {
 60                     break;
 61                 }
 62                 Node endKNext = endK.next;
 63                 while (cur != endKNext) {
 64                     Node next = cur.next;
 65                     cur.next = pre;
 66                     pre = cur;
 67                     cur = next;
 68                 }
 69                 // 翻转后此时 endK 和 startK 分别是是 k 个一组链表中的首尾结点
 70                 startKPre.next = endK;
 71                 startK.next = endKNext;
 72 
 73                 // 当前的 k 个一组翻转完了,开始下一个 k 个一组的翻转
 74                 startKPre = startK;
 75                 step = 0;
 76             } else {
 77                 step++;
 78             }
 79             tmp = tmpNext;
 80         }
 81     }
 82 
 83     /**
 84      * 变形题 1:给定一个链表的头结点 head,以及两个整数 from 和 to ,在链表上把第 from 个节点和第 to 个节点这一部分进行翻转。例如:给定如下链表,from = 2, to = 4 head-->5-->4-->3-->2-->1 将其翻转后,链表变成 head-->5--->2-->3-->4-->1
 85      * @param head
 86      * @param fromIndex
 87      * @param toIndex
 88      */
 89     private static void iterationInvertLinkedList(Node head, Integer fromIndex, Integer toIndex) {
 90         // from-1结点
 91         Node fromPre = null;
 92         Node from = null;
 93         Node to = null;
 94         Node toNext = null;
 95         Integer index = 1;
 96         Node temp = head.getNext();
 97         // 记录之前的节点
 98         while (temp != null) {
 99             if(fromIndex-1 == index) {
100                 fromPre = temp;
101             } else if(fromIndex == index) {
102                 from = temp;
103             } else if(toIndex+1 == index) {
104                 toNext = temp;
105             } else if(toIndex == index) {
106                 to = temp;
107             }
108             index++;
109             temp = temp.next;
110         }
111 
112         Node pre = null;
113         Node cur =from;
114         while (cur != toNext) {
115             Node next = cur.getNext();
116             cur.setNext(pre);
117             pre = cur;
118             cur = next;
119         }
120         // 步骤3:将 from-1 节点指向 to 结点(如果从 head 的后继结点开始翻转,则需要重新设置 head 的后继结点),将 from 结点指向 to + 1 结点
121         if (fromPre != null) {
122             fromPre.next = to;
123         } else {
124             head.next = to;
125         }
126         from.next = toNext;
127 
128     }
129 
130     /**
131      * 递归反转链表
132      * @param node
133      * @return
134      */
135     private static Node invertLinkedList(Node node) {
136         if(node.next == null) {
137             return node;
138         }
139         Node newHead = invertLinkedList(node.next);
140         node.next.next = node;
141         node.next = null;
142         return newHead;
143     }
144 
145     /**
146      * 非递归反转
147      * @param node
148      */
149     private static void iterationInvertLinkedList(Node node) {
150         Node pre = null;
151         Node cur = node.next;
152         while (cur != null) {
153             Node next = cur.next;
154             cur.setNext(pre);
155             pre = cur;
156             cur = next;
157         }
158         node.setNext(pre);
159 
160     }
161 
162     /**
163      * 打印节点
164      */
165     private static void printNode(Node temp) {
166         Node cur = temp.next;
167         while (cur != null) {
168             if(cur.next != null) {
169                 System.out.print(cur.getValue()+"->");
170             } else {
171                 System.out.print(cur.getValue());
172             }
173             cur = cur.next;
174         }
175     }
176 
177     /**
178      * 添加节点
179      * @param num
180      */
181     private static void addNode(int num) {
182         Node cur = head;
183          while (cur.next != null) {
184              cur = cur.next;
185          }
186          cur.next = new Node(num);
187     }
188 
189     static class Node {
190         private Integer value;
191         private Node next;
192 
193         public Node(Integer value) {
194             this.value = value;
195         }
196 
197         public Integer getValue() {
198             return value;
199         }
200 
201         public void setValue(Integer value) {
202             this.value = value;
203         }
204 
205         public Node getNext() {
206             return next;
207         }
208 
209         public void setNext(Node next) {
210             this.next = next;
211         }
212     }
213 }