java解决合并两个有序链表问题

问题:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

链表的定义如下:

public class ListNode {
      int val;
      ListNode next;
      ListNode() {}
      ListNode(int val) { this.val = val; }
      ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

问题分析:

我看到这个题目后首先想到了几个方法如下:

1)定义两个数组分别存储两个链表的值,再合并为一个新的数组,最后根据合并后的数组创建链表。

 这种方法的优点是数组能随时调用每一个值,而链表只能往后遍历,很容易想到这种方法。但是缺点也很明显,创建数组存储链表中的值耗费内存空间,且遍历两条链表后,还要遍历新数组,非常耗时。

2)定义一条新的链表,同时遍历两条链表并比较遍历到的结点的值,较小的值加入到新链表。

这种方法相较于第一种方法,内存空间占用小,且只遍历两条链表各一次,执行较快。但是由于链表结构的特殊性,需要考虑结点是否为null,其中一个链表已经遍历完毕的判断及处理,实现较第一种方法更难一些。值得注意的是:这里创建一个新的链表,原链表的的结点并没有改变。

3)上面两种方法是我看到题目就能立马想到的方法。第一种方法容易实现但是耗时长,内存占用多。第二种虽然耗时较短,但是新链表合并了两个链表内存占用还是不小的。

于是经过我仔细思考我得到了第三种方法。

由于并没有要求不能改变原链表结点,所有可以将其中一条链表插入另一条完成合并。我采用的就是这种方式。

具体解决思路如下:

1)链表问题先判断空链表的情况
2)根据两个链表首个结点的值的大小,决定哪个为返回链表,哪个为插入链表
          具体规则:
                  如果list1.val <= list2.val list1为返回链表,list2为插入链表
3)链表的插入规则:
          l1返回链表正在遍历的结点
          l2:插入链表正在遍历的结点
          1、如果l1.nextnull,则此时l1遍历到返回链表的尾部,那么l2及剩余结点的值一定大于l1,此时指向l2再放回链表就可以了。
          2、如果l2.val介于l1l1.next之间,获取l2的值创建新结点,再插入新结点到l1
          3、如果l2中不能插入,即不满足上述条件,则l1往后继续遍历

 

具体的代码实现:

 public ListNode mergeTwoLists(ListNode list1, ListNode list2) {

        //链表为空的判断
        if(list1 == null && list2 == null){
            return null;
        }else if(list1 == null){
            return list2;
        }else if(list2 == null){
            return list1;
        }


        //用于指向list1中正在遍历的结点
        ListNode l1 = null;
        //用于指向list2中正在遍历的结点
        ListNode l2 = null;
        //用于指向返回链表
        ListNode l = new ListNode();

        /*
            根据首个元素值的大小决定哪个链表作为返回链表,哪个作为插入链表
            例如:
            list1.val <= list2.val
            则将list2作为插入链表,将list2中的结点插入到list1中
         */
        if(list1.val <= list2.val){
            l1 = list1;
            l2 = list2;
            l.next = list1;
        }else{
            l1 = list2;
            l2 = list1;
            l.next = list2;
        }

        //l2为插入链表,则只要l2没有结点则循环结束
        while(l2 != null){

            if(l1.next == null){//如果遍历到了l1尾部,那么l2剩余的结点元素一定比l1尾部的值大,
                l1.next = l2;
                return l.next;
            }else if(l2.val >= l1.val && l2.val < l1.next.val){//如果l2的元素值介于l1的两个结点中间,则插入该结点
                ListNode tmp = l1.next;
                l1.next = new ListNode(l2.val);//创建一个值与l2值相同的结点,再插入到l1
                l1.next.next = tmp;

                l1 = l1.next;
                l2 = l2.next;
            }else{//无插入操作则后移
                l1 = l1.next;
            }
        }
        return l.next;
    }

备注:我实现时是取出插入链表的值再插入到返回链表,仍然占用了一部分内存。如果想继续优化则需要用临时结点,直接插入会找不到返回链表的剩余结点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个Java的示例代码,用于合并两个有序链表: ```java class ListNode { int val; ListNode next; ListNode(int val) { this.val = val; } } public class MergeTwoSortedLists { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(0); ListNode current = dummy; while (l1 != null && l2 != null) { if (l1.val < l2.val) { current.next = l1; l1 = l1.next; } else { current.next = l2; l2 = l2.next; } current = current.next; } if (l1 != null) { current.next = l1; } if (l2 != null) { current.next = l2; } return dummy.next; } } ``` 这个代码中,我们定义了一个`ListNode`类来表示链表节点,每个节点都有一个整数值`val`和一个指向下一个节点的指针`next`。然后,我们创建了一个名为`MergeTwoSortedLists`的类,其中包含了一个`mergeTwoLists`方法,用于合并两个有序链表。我们使用了一个虚拟节点`dummy`来简化代码逻辑。 在`mergeTwoLists`方法中,我们使用两个指针`l1`和`l2`分别指向两个链表的头节点,然后我们比较两个节点的值,将较小的节点链接到结果链表中,并将对应的指针向后移动一位。重复这个过程,直到其中一个链表遍历完。最后,我们将剩余未遍历完的链表直接链接到结果链表的末尾。 最后,我们返回虚拟节点`dummy`的下一个节点作为合并后的链表头节点。 请注意,这只是一个示例代码,你可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值