数据结构之链表面试题汇总(二)-有序单向链表的合并、单向链表反转

来源:互联网 发布:数据的统计 编辑:程序博客网 时间:2024/06/08 15:52

date: 2016-08-18 9:13:00
title: 数据结构之链表面试题汇总(二)-有序单向链表的合并、单向链表反转
categories: 数据结构

版权声明:本站采用开放的[知识共享署名-非商业性使用-相同方式共享 许可协议]进行许可

所有文章出现的代码,将会出现在我的github中,名字可以根据类全名来找,我在github中的文件夹也会加目录备注。


合并两个有序的单向链表,合并之后的链表依然有序【出现频率高】(剑指offer,题17)

思路:

  • 若两个链表本来有序,在合并的时候,可以参照一下归并排序的归并部分,原理一样。

  • 先比较两条链表的节点,先把小的放进新链表,当其中一条链表到达最后一个节点的时候结束循环

  • 在结束循环后判断那条链表为空,然后直接设置下一个节点为另外一个链表的节点即可,这样就可以把剩下的节点都连接上

图解:

public class MergeList {    public static Node mergeList(Node head1, Node head2) {        // first judge 2 head is null together        if (head1 == null && head2 == null) {            throw new RuntimeException("the 2 of them are null");        }        // judge if one of them is null then return another        if (head1 == null)            return head2;        if (head2 == null)            return head1;        // declare two variables to record the newHead and current pointers        Node newHead;        Node current;        // get the first in the new node        if (head1.getRecord() < head2.getRecord()) {            newHead = head1;            current = head1;            head1 = head1.getNext();        } else {            newHead = head2;            current = head2;            head2 = head2.getNext();        }        // loop that put the less one to the list and update the position while        // one of them is null        while (head1 != null && head2 != null) {            if (head1.getRecord() < head2.getRecord()) {                current.setNext(head1);                current = current.getNext();                head1 = head1.getNext();            } else {                current.setNext(head2);                current = current.getNext();                head2 = head2.getNext();            }        }        // if one of them are null which indicates that the other is not null        // and put        if (head1 == null) {            current.setNext(head2);        }        if (head2 == null) {            current.setNext(head1);        }        // is to the list        // return new list        return newHead;    }}

测试代码: 第二个链表中的元素都比第一个链表的元素大

public class ReverseLinkedListTest {    public static void main(String[] args) {        Node node1 = new Node(1);        Node node2 = new Node(2);        Node node3 = new Node(3);        Node node4 = new Node(4);        node1.setNext(node2);        node2.setNext(node3);        node3.setNext(node4);        Node list1 = new Node(7);        Node list2 = new Node(8);        Node list3 = new Node(9);        Node list4 = new Node(10);        list1.setNext(list2);        list2.setNext(list3);        list3.setNext(list4);        RecustionAllElementOfLinkedList.printAllElements(MergeList.mergeList(                node1, list1));    }}

运行结果:

测试代码二:第二个链表中有与第一个链表相同的元素:

public class ReverseLinkedListTest {    /**     * @param args     */    public static void main(String[] args) {        Node node1 = new Node(1);        Node node2 = new Node(2);        Node node3 = new Node(3);        Node node4 = new Node(4);        node1.setNext(node2);        node2.setNext(node3);        node3.setNext(node4);        Node list1 = new Node(1);        Node list2 = new Node(2);        Node list3 = new Node(6);        Node list4 = new Node(7);        list1.setNext(list2);        list2.setNext(list3);        list3.setNext(list4);        RecustionAllElementOfLinkedList.printAllElements(MergeList.mergeList(                node1, list1));    }}

运行结果:

单链表的反转【出现频率最高】(剑指offer,题16)

思路:

  • 可以考虑用栈来存放链表中的元素,然后再通过弹栈来存入新链表中来实现该功能,但是这样做不高效

  • 也可以考虑用数组存放链表中的元素,然后通过倒序获取数组中的元素来实现

  • 在这里主要讨论使用递归实现单向链表的反转

    • 首先判断节点是否为空,为空抛异常
    • 接着得到当前节点的下一个节点
    • 把当前节点的下一个节点设置成null
    • 把下一个节点作为参数递归调用,返回的是最后一个节点
    • 把下一个节点的下一个节点设置成当前节点,下一个节点为5 当前节点为4 结果为5.setNext(4)
    • 还有4 3,3 2 ,2 1 完成之后返回递归返回的节点,即新链表的头节点

图解

代码实现:包含使用栈、双指针、递归的方法

public class ReverseLinkedListUtil {    /**     * use stack to reverse single-direction LinkedList     *      * @param head     *            the head of a LinkedList     * @return the new head of a LinkedList     */    public static Node reverseByStack(Node head) {        Stack<Node> nodes = new Stack<Node>();        if (head == null) {            throw new RuntimeException("the Node is null !");        }        // put all the node to the stack        while (head != null) {            nodes.push(head);            head = head.next;        }        // get all the node in the stack        head = nodes.pop();        Node curNode = head;        while (!nodes.isEmpty()) {            // update the next of the node            Node nextNode = nodes.pop();            nextNode.setNext(null);            curNode.setNext(nextNode);            curNode = nextNode;        }        // return the new head        return head;    }    /**     * use 2 pointers to reverse the single-direction LinkedList     *      * @param head     *            the head of a single-direction LinkedList     * @return the new head of a single-directionLinkedList     */    public static Node reverseByPointer(Node head) {        // define the previous node to record the previous node        Node previous = null;        // judge that the current node is null        while (head != null) {            // if true move the 2 pointers backward            // get the next node and record it            Node next = head.getNext();            // set the next.next to previous            head.setNext(previous);            // set the previous to current (head)            previous = head;            // set the next to next            head = next;        }        // else break out the loop        return previous;    }    /**     * use recursion to reverse the single-direction LinkedList     *      * @param head     *            the head of the LinkedList     * @return the new-head of the LinkedList that has been reversed     */    public static Node reverseByRecur(Node head) {        // if the tail is reached return it        if (head == null || head.next == null)            return head;        // get the next node        Node nextNode = head.getNext();        // set the current node's next node to null        head.setNext(null);        // recursion        Node recursionResult = reverseByRecur(nextNode);        // set the next node's next node to current        nextNode.setNext(head);        // return the value that was returned from the recursion        return recursionResult;    }}

测试代码:

public class ReverseLinkedListTest {    /**     * @param args     */    public static void main(String[] args) {        Node node1 = new Node(1);        Node node2 = new Node(2);        Node node3 = new Node(3);        Node node4 = new Node(4);        Node node5 = new Node(5);        node1.setNext(node2);        node2.setNext(node3);        node3.setNext(node4);        node4.setNext(node5);        RecustionAllElementOfLinkedList.printAllElements(ReverseLinkedListUtil                .reverseByRecur(node1));    }}

运行结果:


原创粉丝点击