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

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));
    }

}

运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值