前言

本博文部分图片, 思路来自于剑指offer 或者编程珠玑

问题描述

10 归并两个有序链表_头结点


现在有两个有序链表的头结点, 试图将两个链表归并到一个链表中, 是一道 很常见的一道题目

思路

两种思路, 一种基于循环, 一种基于递归, 后者简洁的多

思路一 : 首先判断两个链表的第一个结点的大小 确定头结点, 然后利用一个循环进行归并, 直到归并到某一个链表末尾, 然后接上另外一个链表的剩余数据即可

思路二 : 判断两个链表的第一个结点的大小 获取较小的结点[这里 假设是从小到大], 然后设置该节点的下一个结点为归并该节点剩余的链表 和另外的一个链表的结果, 返回该较小节点 [注意这里的递归]

参考代码

/**
 * file name : Test01MergeTwoList.java
 * created at : 8:28:20 PM Jun 5, 2015
 * created by 
 */

package com.hx.test05;

public class Test01MergeTwoList {

    // 归并两个有序链表
    public static void main(String []args) {
        LinkedList ll01 = new LinkedList();
        LinkedList ll02 = new LinkedList();
        int max = 20;

        for(int i=0; i<max; i+=3) {
            ll01.add(i);
        }
        for(int i=1; i<max; i+=2) {
            ll02.add(i);
        }

        Node head = mergeTwoList01(ll01.first(), ll02.first());
//      Node head = mergeTwoList02(ll01.first(), ll02.first());

        Node tmp = head;
        while(tmp != null) {
            Log.logWithoutLn(tmp.getData() + " ");
            tmp = tmp.getNext();
        }

    }

    // 归并两个顺序的链表
    // 先确定头结点, 更新头结点所在的链表的索引到下一个元素, 设置cur索引为头结点[单独确立头结点]
    // 开始归并  知道到达任意链表的末尾, 如果比较两个链表的当前元素, 设置cur.next为较小的元素, 然后更新该较小元素所在的链表的索引, 继续比较
    // 当遍历到某一个链表的末尾之后  设置cur.next为另一个链表的索引
    public static Node mergeTwoList01(Node first, Node first2) {
        if(first == null) {
            return first2;
        }
        if(first2 == null) {
            return first;
        }

        Node res = null, cur = null;
        if(first.getData() < first2.getData()) {
            res = first;
            first = first.getNext();
        } else {
            res = first2;
            first2 = first2.getNext();
        }
        cur = res;
        while(first != null && first2 != null) {
            if(first.getData() <= first2.getData() ) {
                cur.setNext(first);
                first = first.getNext();
            } else {
                cur.setNext(first2);
                first2 = first2.getNext();
            }
            cur = cur.getNext();
        }

        if(first == null) {
            cur.setNext(first2);
        } else {
            cur.setNext(first);
        }

        return res;
    }

    // 递归版本的合并两个有序链表
    public static Node mergeTwoList02(Node first, Node first2) {
        if(first == null) {
            return first2;
        }
        if(first2 == null) {
            return first;
        }

        Node res = null;
        if(first.getData() < first2.getData()) {
            res = first;
            res.setNext(mergeTwoList02(first.getNext(), first2) );
        } else {
            res = first2;
            res.setNext(mergeTwoList02(first, first2.getNext()) );
        }

        return res;
    }


}

效果截图

10 归并两个有序链表_数据结构_02

总结

这种思路 应该在我们学习归并排序的时候, 就应该使用过吧, 因为递归处理省略了对于链表遍历的循环, 以及对于两个链表中某一个链表为空的结尾的处理[传递到了下一次方法递归来处理], 所以 看起来简洁的多

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!