0.目录
1.循环控制
2.Java代码实现
- 2.1 创建链表和递归反转实现
- 2.2 循环反转思路
- 2.3 链表反转的实现
- 2.4 测试用例
- 2.5 循环控制-创建链表
1.循环控制
循环书写方法:
- 定义循环不变式,并在循环体每次结束后保持循环不变式
- 先一般 ,后特殊
- 每次 必须 向前推进循环不变式中涉及的变量值
- 每次推进的规模必须为 1
循环不表示(loop invariant):是一句断言定义各变量所满足的条件
2.Java代码实现
2.1 创建链表和递归反转实现
前面已经写过递归的版本了,传送门:
递归控制-链表反转
本篇结点和创建链表的实现同前文 递归控制-创建链表
2.2 循环反转思路
1.先考虑循环中的某一个情况——循环到3时,应该要实现哪些操作?
2.此时应该要把3 → 4的指针改为3 → 2,而4作为剩下的第一个结点。
为了实现这一功能,加入两个指针newHead(指向反转成功的链表)和curHead(指向还没有反转的链表):
3.所以每一次循环做的操作就是跟随两个指针往后移:
4.总体来看就是用两个指针从头循环到尾一步步地反转链表:
2.3 链表反转的实现
依据反转思路实现循环代码即可。
public Node reverseLinkedList(Node head) {
Node newHead = null;
Node curHead = head;
// Loop invariant:
// newHead points to the linked list already reversed.
// curHead points to the linked list not yet reversed.
while (curHead != null) {
// Loop invariant holds.
Node next = curHead.getNext();
curHead.setNext(newHead);
newHead = curHead;
curHead = next;
// Loop invariant holds.
}
// Loop invariant holds.
return newHead;
}
ps:不需要在开头处理:if(head = null)
,程序也能够很好的处理特殊情况。
验证在循环最后一步时程序的正确性:
while (curHead != null) {
// Loop invariant holds.
Node next = curHead.getNext(); // next = null
curHead.setNext(newHead); // curHead.next reversed
newHead = curHead; // newHead points to last
curHead = next; // curHead = null
// Loop invariant holds.
}
2.4 测试用例
测试程序是否正确运行(采用之前递归实现的测试用例):
public static void main(String[] args) {
LinkedListCreator creator = new LinkedListCreator();
LinkedListReverser reverser = new LinkedListReverser();
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(new ArrayList<>())));
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(Arrays.asList(1))));
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(Arrays.asList(1, 2, 3, 4, 5))));
}
运行结果为
main所在java文件全部代码:
import java.util.ArrayList;
import java.util.Arrays;
import interview.common.Node;
import interview.recursion.LinkedListCreator;
public class LinkedListReverser {
public Node reverseLinkedList(Node head) {
Node newHead = null;
Node curHead = head;
// Loop invariant:
// newHead points to the linked list already reversed.
// curHead points to the linked list not yet reversed.
while (curHead != null) {
// Loop invariant holds.
Node next = curHead.getNext();
curHead.setNext(newHead);
newHead = curHead;
curHead = next;
// Loop invariant holds.
}
// Loop invariant holds.
return newHead;
}
public static void main(String[] args) {
LinkedListCreator creator = new LinkedListCreator();
interview.recursion.LinkedListReverser reverser = new interview.recursion.LinkedListReverser();
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(new ArrayList<>())));
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(Arrays.asList(1))));
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(Arrays.asList(1, 2, 3, 4, 5))));
}
}
2.5 循环控制-创建链表
最后再把创建链表的递归实现也改为循环实现:
public Node createLargeLinkedList(int size) {
Node prev = null;
Node head = null;
for (int i = 1; i <= size; i++) {
Node node = new Node(i);
if (prev != null) {
prev.setNext(node);
} else {
head = node;
}
prev = node;
}
return head;
}
测试一下:
public static void main(String[] args) {
LinkedListCreator creator = new LinkedListCreator();
interview.recursion.LinkedListReverser reverser = new interview.recursion.LinkedListReverser();
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(new ArrayList<>())));
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(Arrays.asList(1))));
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLinkedList(Arrays.asList(1, 2, 3, 4, 5))));
Node.printLinkedList(reverser.reverseLinkedList(
creator.createLargeLinkedList(100)));
}
运行结果: