编码技巧之循环【笔记】

编码技巧之循环【笔记】

循环控制

在循环中要定义一个循环不变式

循环不变式是一句断言定义各变量所满足的条件

与递归不同,在递归里面断言就是证明一个函数,而在循环中,是没法直接看到的,是心中默认的一个条件

循环的书写方法

定义一个循环不变式,并在循环体每次结束后保持循环不变式

和递归一样,先一般情况,然后再特殊情况

每次必须向前推进循环不变式中涉及的变量值,且每次推进的规模不能多,必须为1

例题一:链表反转

将1->2->3->4->5->null变成null<-1<-2<-3<-4<-5

与递归的想法不同,循环的话不能将第一个单独提出来,因为这样要考虑很多的边界问题,因此可以在链表中间切一刀,将前三个反转以后可以发现就是头和尾变化了,此时可以设置两个变量来维持

其中newhead指向反转成功的链表,currenthead指向还没有成功反转的链表,这就是循环不变式,每次循环都必须遵守,推进以后

只要当newhead从null移动到5的时候,currenthead移动到null的时候,就可以确定整个链表反转完成了

具体代码如下:

package interview.loop;

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.

// Loop invariant holds.
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();
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))));
System.out.println("done");
}
}

例题二:链表中的节点删除(delete_if)

将1->2->3->2->5->null中的所有数值为2的节点全部删除,删除以后变为1->3->5->null

设置一个变量previous指向对应的节点,在删除后面的节点以后previous不需要移动,不然在遇到两个连续的需要删除的节点的时候会错过一个

循环不变式是要保证所有的数值为2的节点能够被正确的删除

如果头结点没有previous怎么办?

进行特殊处理或者增加虚拟的头结点

具体代码如下:

package interview.loop;

import java.util.ArrayList;
import java.util.Arrays;

import interview.common.Node;
import interview.recursion.LinkedListCreator;

public class LinkedListDeletor {

public Node deleteIfEquals(Node head, T value) {
while (head != null && head.getValue() == value) {
head = head.getNext();
}

if (head == null) {
return null;
}

Node prev = head;
// Loop invariant: list nodes from head up to prev has been
// processed. (Nodes with values equal to value are deleted.)
while(prev.getNext() != null) {
if (prev.getNext().getValue() == value) {
// delete it
prev.setNext(prev.getNext().getNext());
} else {
prev = prev.getNext();
}
}

return head;
}

public static void main(String[] args) {
LinkedListCreator creator = new LinkedListCreator();
LinkedListDeletor deletor = new LinkedListDeletor();
Node.printLinkedList(deletor.deleteIfEquals(
creator.createLinkedList(Arrays.asList(1, 2, 3, 2, 5)),
2));
Node.printLinkedList(deletor.deleteIfEquals(
creator.createLinkedList(Arrays.asList(1, 2, 3, 2, 2)),
2));
Node.printLinkedList(deletor.deleteIfEquals(
creator.createLinkedList(Arrays.asList(1, 2, 3, 2, 2)),
1));
Node.printLinkedList(deletor.deleteIfEquals(
creator.createLinkedList(Arrays.asList(2, 2, 3, 2, 2)),
2));
Node.printLinkedList(deletor.deleteIfEquals(
creator.createLinkedList(Arrays.asList(2, 2, 2, 2, 2)),
2));
Node.printLinkedList(deletor.deleteIfEquals(
creator.createLinkedList(Arrays.asList(2)),
2));
Node.printLinkedList(deletor.deleteIfEquals(
creator.createLinkedList(Arrays.asList(2)),
1));
Node.printLinkedList(deletor.deleteIfEquals(
creator.createLinkedList(new ArrayList()),
1));
}
}

posted @ 2021-03-02 13:45  DbWong_0918  阅读(150)  评论(0)    收藏  举报