阿里面试题: 将两个升序链表合并成一个升序链表

Posted Dream_it_possible!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里面试题: 将两个升序链表合并成一个升序链表相关的知识,希望对你有一定的参考价值。

题目

        将两个升序链表合并,合并后还是一个升序列表,尽量用最小的时间复杂度。

思路一

        两个链表合成一个链表,可以将两个链表打散,然后按照大小顺序放入到一个数组里,冒泡排序后,将节点串起来,这样就可以实现一个升序链表。

思路二

        思路一方法虽然可行,但是时间复杂度大于O(N2), 还重新创建了一个新数组去装这些元素, 空间复杂度也是比较大,因此方案一不可取。

        我们可以利用两个升序链表的特点: 可以按照顺序进行遍历,具体实现步骤如下:

        1)  定义一个新链表的头节点为两个链表中头节点的最小值。

 Node root=Max(l1.head.data,l2.head.data)

        2) 将剩下的两个链表,按照头头比较的规则,将值小的节点接入到新链表的尾节点, 因为每次我们就是取两个值,这两个值中肯定较小值肯定比新链表的尾节点的值要大,因此可以采用递归的思想来实现。

什么是头头比较?

        我们每次拿出两个链表的头节点,值小的节点插入到新链表尾,然后在旧链表中删除该节点。

        3) 递归结束的条件。 当任意一个链表结束时,也就意味着遍历结束和递归结束。如果是刚好比较完,那么就返回NULL插入到新链表的尾部,如果有一个链表遍历完了,另外一个链表还多余了很多节点,那么就直接将剩余的节点插入到新链表的尾部即可,因为每次递归(比较完毕后)旧链表中剩下的值总是大于或等于新链表的最大值。
 

import chain.ReverseList;

/**
 * @decription:
 * @author: zhengbing.zhang
 * @date: 2021/7/9 10:50
 * 将两个升序链表合并,合并后还是一个升序列表,尽量用最小的时间复杂度。
 * 1->3-5>7
 * 2->4->5->8
 * 2  3  3 4
 * 1 1 2 3
 */
public class LinkedListMerge {

    static Node one;

    static Node two;

    static {
        one = new Node(1, new Node(3, new Node(5, new Node(7, null))));
        two = new Node(2, new Node(4, new Node(5, new Node(8, new Node(9, null)))));
    }

    static class Node {
        Integer data;
        Node next;

        public Node(Integer data, Node next) {
            this.data = data;
            this.next = next;
        }

        public Integer getData() {
            return data;
        }

        public void setData(Integer data) {
            this.data = data;
        }

        // 使用递归的思想遍历链表
        public String traverse() {
            return this.getData() + "->" + (this.next == null ? "NULL" : this.next.traverse());
        }
    }


    /**
     *  定义好头节点后,因为两个链表都是升序的,我们可以把每次的操作分解为三步:  比较两个链表的头节点 ->  将小的节点插入到新链表的尾节点-> 旧链表的节点移除。
     *  递归结束的条件: 任意一个链表为空链表。
     * @param l1
     * @param l2
     * @param node
     * @return
     */
    public static Node mergeLists(Node l1, Node l2, Node node) {
        // 如果有链表先为空,那么就将另外一个链表接入到新的链表上
        if (l1 == null) {
            node.next = l2;
            return node;
        }
        if (l2 == null) {
            node.next = l1;
            return node;
        }
        // 定义好头节点后,分别比较两个链表中的元素,哪个小哪个就先插入到新链表的后面,每次插完后,删除链表节点(移到下一个节点)
        if (l1.getData() > l2.getData()) {
            node.next = new Node(l2.getData(), null);
            l2 = l2.next;
        } else {
            node.next = new Node(l1.getData(), null);
            l1 = l1.next;
        }
        return mergeLists(l1, l2, node.next);
    }


    public static void main(String[] args) {
        Node current;
        // 定义新链表的头节点
        if (one.getData() > two.getData()) {
            current = new Node(two.getData(), null);
            two = two.next;
        } else {
            current = new Node(one.getData(), null);
            one = one.next;
        }
        mergeLists(one, two, current);
        System.out.println(current.traverse());
    }
}

打印结果:

此方法的最坏时间复杂度为o(n),如果链表的长度差距很大的话,最后可以少比较很多次。

以上是关于阿里面试题: 将两个升序链表合并成一个升序链表的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# LeetCode面试题:合并两个有序链表

链表相关面试题第二篇

程序员代码面试指南第二版 12.打印两个升序链表的公共部分

Leetcode练习(Python):链表类:第21题:合并两个有序链表:将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

链表习题-将两个递增单链表合并成一个递减单链表

两条带头结点的升序重复合并成一个无重复的升序链表