• 【算法】LeetCode算法题-Merge Two Sorted List


    这是悦乐书的第148次更新,第150篇原创

    01 看题和准备

    今天介绍的是LeetCode算法题中Easy级别的第7题(顺位题号是21)。合并两个已排序的链表并将其作为新链表返回。 新链表应该通过拼接前两个链表的节点来完成。例如:

    链表L1包含三个节点,为1,2,4
    链表L2包含三个节点,为1,3,4
    将L1和L2合并后的新链表包含6个节点,为1,1,2,3,4,4

    本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

    02 此题中的链表是什么?

    先来看段代码,下面是定义的ListNode类,有两个属性,一个是存储整数值的val,一个是ListNode类本身的next,存储下一个ListNode的地址值(指针)。形象的解释就是,链表可以是拉链的齿轮,互相咬合;也可以是电影《盗梦空间》中的梦中梦;就像大盒子里面可以继续放盒子一样。

    class ListNode {
    	int val;
    	ListNode next;
    	ListNode(int x) {
    		val = x;
    	}
    }
    

    为了更好的理解链表是怎么存储值的,且看下面的代码。l1的next属性引用了l2,l2的next属性引用了l3。

    public class Easy_21_MergeTwoSortedList {
    
    	public static void main(String[] args) {
    		Easy_21_MergeTwoSortedList instance = new Easy_21_MergeTwoSortedList();
    		ListNode l1 = new ListNode(1);
    		ListNode l2 =new ListNode(2);
    		ListNode l3 =new ListNode(4);
    		l1.next = l2;
    		l2.next = l3;	
    		System.out.println(instance.listNodeToString(l1));
    		ListNode l4 = new ListNode(1);
    		ListNode l5 =new ListNode(3);
    		ListNode l6 =new ListNode(4);
    		l4.next = l5;
    		l5.next = l6;
    		System.out.println(instance.listNodeToString(l4));
    	}
    	
    	public String listNodeToString(ListNode L){
    		List<Integer> list = new ArrayList<Integer>();
    		while(L != null){
    			list.add(L.val);
    			L = L.next;
    		}
    		return list.toString();
    	}
    }
    

    03 第一种解法

    因为给的链表都是已经排过序的(由小到大),只需要依次比较两个链表的元素val值即可,并且存入一个新的链表里面。如果某一个链表先循环完,新链表剩下的元素就是另外一个链表剩下的元素。

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1); 
        ListNode cur = dummy;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = (l1 != null) ? l1 : l2;
        return dummy.next;
    }
    

    04 第二种解法

    像第二种方法循环判断再取值的情况,很容易联想到递归,即自己调用自己,同时给予退出条件即可。使用递归的好处就是代码量少。

    public ListNode mergeTwoLists2(ListNode l1, ListNode l2) {
        if (l1 == null) {
        	return l2;
        }
        if (l2 == null) {
        	return l1;
        }
        if (l1.val < l2.val) {
        	l1.next = mergeTwoLists2(l1.next, l2);
    		return l1;
        } else {
    		l2.next = mergeTwoLists2(l1, l2.next);
    		return l2;
    	}
    }
    

    05 小结

    此题虽然不难,但是需要先将题目意思读懂,并且知道链表是怎么存数据的,这样才能更好解题。为了更好理解,下面贴上全部代码。

    package leetcode;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 合并两个已排序的链接列表并将其作为新列表返回。 新列表应该通过拼接前两个列表的节点来完成。
     * 例:
     * 输入:1-> 2-> 4, 1-> 3-> 4
     * 输出:1-> 1-> 2-> 3-> 4-> 4
     * @author 小川94
     * @date 2018-10-21
     */
    public class Easy_21_MergeTwoSortedList {
    
    	public static void main(String[] args) {
    		Easy_21_MergeTwoSortedList instance = new Easy_21_MergeTwoSortedList();
    		ListNode l1 = new ListNode(1);
    		ListNode l2 =new ListNode(2);
    		ListNode l3 =new ListNode(4);
    		l1.next = l2;
    		l2.next = l3;	
    		System.out.println(instance.listNodeToString(l1));
    		ListNode l4 = new ListNode(1);
    		ListNode l5 =new ListNode(3);
    		ListNode l6 =new ListNode(4);
    		l4.next = l5;
    		l5.next = l6;
    		System.out.println(instance.listNodeToString(l4));
    		ListNode result = instance.mergeTwoLists2(l1, l4);
    		System.out.println(instance.listNodeToString(result));
    	}
    	
    	public String listNodeToString(ListNode L){
    		List<Integer> list = new ArrayList<Integer>();
    		while(L != null){
    			list.add(L.val);
    			L = L.next;
    		}
    		return list.toString();
    	}
    	
    	/**
    	 * 顺位循环判断
    	 * @param l1
    	 * @param l2
    	 * @return
    	 */
    	public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    	    ListNode dummy = new ListNode(-1); 
    	    ListNode cur = dummy;
    	    while (l1 != null && l2 != null) {
    	        if (l1.val < l2.val) {
    	            cur.next = l1;
    	            l1 = l1.next;
    	        } else {
    	            cur.next = l2;
    	            l2 = l2.next;
    	        }
    	        cur = cur.next;
    	    }
    	    cur.next = (l1 != null) ? l1 : l2;
    	    return dummy.next;
    	}
    
    	/**
    	 * 利用递归
    	 * @param l1
    	 * @param l2
    	 * @return
    	 */
    	public ListNode mergeTwoLists2(ListNode l1, ListNode l2) {
    	    if (l1 == null) {
    	    	return l2;
    	    }
    	    if (l2 == null) {
    	    	return l1;
    	    }
    	    if (l1.val < l2.val) {
    	    	l1.next = mergeTwoLists2(l1.next, l2);
    			return l1;
    	    } else {
    			l2.next = mergeTwoLists2(l1, l2.next);
    			return l2;
    		}
    	}
    	
    }
    
    class ListNode {
    	int val;
    	ListNode next;
    	ListNode(int x) {
    		val = x;
    	}
    }
    

    此题解法远不止上面这两种,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

  • 相关阅读:
    12.数组三--数组的冒泡排序与快速排序
    11.数组二
    10.数组一
    Vue之组件与父子传值
    Django模型层
    面向对象的组合用法
    面向对象初识
    Python内置函数
    列表推导式,生成器表达式
    装饰器进阶
  • 原文地址:https://www.cnblogs.com/xiaochuan94/p/9827151.html
Copyright © 2020-2023  润新知