Java面试--面试中常考的循环问题

面试中常考的循环问题

一、循环控制

循环不变式(loop invariant)

循环书写方法

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

2.先一般、后特殊

3.每次 必须  向前推进循环不变式中涉及的变量值

4.每次推进的规模必须为 1

例 1.链表反转

步骤:

1.定义循环不变式

【在链表中间"切一刀",循环进行到一半、切在 3 和 4 之间,循环了3次,已经将1、2、3这几个节点处理完毕了,4、5还没有动,这就是循环,前几个节点处理完毕后,形态如下图所示】

2.newHead 指向反转成功的链表、currentHead 指向还没有反转的链表 

3.将 newHead 和 currentHead 向前推进 1 ;

4. newHead 必须指向已经反转完成的链表的头,但什么都没有做,已经反转完成链表的头是 Null,故 newHead 指向  Null;

current 指向还没有进行反转的链表的头,但此时还没有进行反转,故 current 指向的是 1 ;

上述满足循环不变式

5.开始向右推进,推进到 newHead 指向 5 , currentHead 指向 1;

代码实现:LinkedListReverser.java

package interview.loop;

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

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

public class LinkedListReverser {

  public <T> Node<T> reverseLinkedList(Node<T> head) {
    Node<T> newHead = null;
    Node<T> 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<T> next = curHead.getNext();
      curHead.setNext(newHead);	//成功反转
      newHead = curHead;	//将 newHead 右移
      curHead = next;	//将 curHead 右移
      // 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))));

    reverser.reverseLinkedList(
        creator.createLargeLinkedList(1000000));
    System.out.println("done");
  }
}

输出:

例 2 链表中删除节点

将所有元素为 2 的节点删除掉

删除后

假设第一个 2 已经被删除掉了

删除第二个 2 :将 currentNext 指向 5 即可,3 的继承指向 5 即可;

要将 3 的  next 的指针指向 5 ,首先要有一个指针 previous 指向 5 

然后 jvm 的垃圾回收机制会将 2 销毁掉

问题:头节点没有 previous 怎么办?

1.特殊处理

2.增加虚拟头节点

代码实现:LinkedListDeletor.java

package interview.loop;

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

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

public class LinkedListDeletor {

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

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

    Node<T> 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();	//不需要删除则将 prev 向后移动一个
      }
    }

    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<Integer>()),
        1));
  }
}

输出:

猜你喜欢

转载自blog.csdn.net/jianghao233/article/details/82801809
今日推荐