题目:合并两个已排序链表

难度:Easy

题目内容

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

翻译

合并两个已排序的链表,并将其作为一个新链表返回。新的链表应该通过将前两个列表的节点拼接在一起。

Example:

Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4

我的思路:数据结构——已经指定链表,且不需要特殊操作,就用链表;

     算法——对一个链表进行遍历,如果链表2节点的值小于当前节点,就插入到它前面。

        因为是单链表,所以需要前驱指针一起移动才能进行操作,并且还需要一个头节点作为返回用。

我的代码

     public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null || l2 == null) {
return l1 == null ? l2 : l1;
} ListNode head = new ListNode(0);
ListNode pre = head;
head.next = l1; while (l1 != null && l2 != null) {
if (l2.val < l1.val) {
pre.next = l2;
l2 = l2.next;
pre.next.next = l1; pre = pre.next; // pre归位
continue; // 插入结束,l1不需要移动
}
pre = l1;
l1 = l1.next;
}
if (l2 != null) {
pre.next = l2; // l2 还有剩的话说明l1已经为null,直接接在pre后面即可
}
return head.next;
}

我的复杂度:  时间: O(M + N)  空间: O(1)

编码过程出现问题

1、在插入l2之后此时l1 是不需要移动的——>continue   出错用例:[5]、[1,2,4]

2、插入后,continue之前,还得把pre往前移动   出错用例:[5]、[1,2,4]

参考答案代码

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

答案复杂度:  时间:O(N+M)    空间:O(N+M)

答案思路

利用递归的思想,每次比较之后,将小的那个节点的后继改为下一次递归返回的节点,然后返回自己。所以最后会返回l1与l2中小的那一个节点,而它的后继是一条完整的由小到大的节点。

比较:我的那个方法空间复杂度比较好,而且由于没有使用递归运行相对较快。而答案方法则简洁明了。



补充

23题:Merge k Sorted Lists



题目:就是21题的两个链表改成了k个

难度:Hard

我的思路:选取节点的思路肯定还是一样,选取k个链表表头中最小的那一个作为下一个节点,但是由于是k个所以在最内层也就是lists[]某一个或某几个为null的时候,就不能像两个链表一样直接返回另外一个那么简单了,就需要把原来lists中的null都给删除,但是由于是数组,所以操作起来比较麻烦得借用list。

这种类似于多排序数组归并,其实最佳选择是堆排序,不过我嫌麻烦就直接顺序搜索最小值了。

我的代码

 class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) {
return null;
} //*** 去除null节点 **//
List<ListNode> l = new ArrayList<ListNode>(Arrays.asList(lists));
boolean hasNull = l.remove(null);
lists = l.toArray(new ListNode[l.size()]);
// end // if (hasNull) {
return mergeKLists(lists);
} ListNode min = getMinNode(lists);
min.next = mergeKLists(lists); return min;
} public static ListNode getMinNode(ListNode[] lists) {
int minIndex = 0;
for (int i = 1; i < lists.length; i++) {
if (lists[i].val < lists[minIndex].val) {
minIndex = i;
}
} ListNode minNode = lists[minIndex];
lists[minIndex] = lists[minIndex].next; // min取出后,lists要更新 return minNode;
}
}

结果:最后一两个用例栈溢出

我的复杂度: 时间:O (N*M)    N是lists的长度,M是lists中最长的那一个

         空间:超级大。。。(因为每一次的去除null,都会新建一个lists的对应的ArrayList,并且toArray又新建了一个对应的Array),所以栈溢出了

优化

那就用简单粗暴的方法去除null:

// 替换去除null //
for (int i = 0; i < lists.length; i++) {
if (lists[i] == null) {
ListNode[] temp = new ListNode[lists.length-1];
for (int j = 0; j < temp.length; j++) {
if (j < i) {
temp[j] = lists[j];
} else {
temp[j] = lists[j+1];
}
}
hasNull = true;
lists = temp;
i--;
}
}
// end//

这样一来就只多建了一个temp的Array。

【注意】:最后在数组删除元素之后不要忘了  i -- ,因为当前的i已经被删除了,最新的lists第i个已经是以前的第i+1个,如果继续循环那么将直接 i ++ 就会跳过之前的那个 i + 1。

优化后结果:不溢出了。。。但是运行超时了。

好吧看来还是得用堆排序——优先队列。

答案代码

 class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode res=null; System.out.println("lists.length "+ lists.length);
if(lists == null || lists.length== 0)
return res; PriorityQueue pq = new PriorityQueue();
for(int i=0; i<lists.length; i++){
if(lists[i]!=null){
pq.offer(new PQNode(lists[i].val, 0, i));
lists[i] = lists[i].next;
}
} for(int i=0; !pq.isEmpty(); i++){
PQNode n = (PQNode)pq.poll();
int value = n.value;
int index = n.index;
int listNumber = n.listNumber;
if(res==null){
res = new ListNode(value);
}
else{
ListNode temp = res;
while(temp.next!=null){
temp=temp.next;
}
temp.next = new ListNode(value);
}
if(lists[listNumber]!=null){
pq.offer(new PQNode(lists[listNumber].val, 0, listNumber));
lists[listNumber] = lists[listNumber].next; }
}
return res;
}
} class PQNode implements Comparable<PQNode>{
int value;
int index;
int listNumber; public PQNode(int value, int index, int listNumber){
this.value = value;
this.index = index;
this.listNumber = listNumber;
} public int compareTo(PQNode obj){
if(this.value < obj.value) return -1;
if(this.value > obj.value) return 1;
return 0;
}
}

答案复杂度: 时间:O (N*logM + M)   空间:O(M)

答案思路:思路没变,不过就是在取k个数组中最小的时候使用了一个优先级队列——最开始将k个链表头取出建立一个优先级队列(java.util.PriorityQueue),然后每次poll

出队头后再放进此队头原来所在链表的链表头,当发现此表头为null的时候,则优先级队列的大小减一。直到队列为空。

LeetCode第[21][23]题(Java):Merge Sorted Lists的更多相关文章

  1. 乘风破浪:LeetCode真题_023_Merge k Sorted Lists

    乘风破浪:LeetCode真题_023_Merge k Sorted Lists 一.前言 上次我们学过了合并两个链表,这次我们要合并N个链表要怎么做呢,最先想到的就是转换成2个链表合并的问题,然后解 ...

  2. 乘风破浪:LeetCode真题_021_Merge Two Sorted Lists

    乘风破浪:LeetCode真题_021_Merge Two Sorted Lists 一.前言 关于链表的合并操作我们是非常熟悉的了,下面我们再温故一下将两个有序链表合并成一个的过程,这是基本功. 二 ...

  3. LeetCode练题——88. Merge Sorted Array

    1.题目 88. Merge Sorted Array——Easy Given two sorted integer arrays nums1 and nums2, merge nums2 into  ...

  4. LeetCode之二叉树作题java

    100. Same Tree Total Accepted: 127501 Total Submissions: 294584 Difficulty: Easy Given two binary tr ...

  5. LeetCode之数组处理题java

    342. Power of Four Total Accepted: 7302 Total Submissions: 21876 Difficulty: Easy Given an integer ( ...

  6. LeetCode之字符串处理题java

    344. Reverse String Write a function that takes a string as input and returns the string reversed. E ...

  7. [LeetCode] 21. Merge Two Sorted Lists 混合插入有序链表

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  8. [LeetCode] Merge Two Sorted Lists 混合插入有序链表

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  9. [LeetCode] Merge Sorted Array 混合插入有序数组

    Given two sorted integer arrays A and B, merge B into A as one sorted array. Note:You may assume tha ...

随机推荐

  1. Zend Studio 中创建简单的phpfile模板和xhtml类phpfile模板

    <!--简单的phpfile模板,带有创建时间和作者--><?php/*** ==============================================* @dat ...

  2. "零代码”开发B/S企业管理软件之二:怎么创建数据源

    声明:该软件为本人原创作品,多年来一直在使用该软件做项目,软件本身也一直在改善,在增加新的功能.但一个人总是会有很多考虑不周全的地方,希望能找到做同类软件的同行一起探讨. 本人文笔不行,能把意思表达清 ...

  3. Collections工具类的使用

    创建实体类 public class News implements Comparable { private int id; //新闻编号 private String title; //新闻标题 ...

  4. shell function/for in/for (())/string concat/has dir/rename using regex/if(())/exit/execute command and pass value to variable/execute python

    #!/bin/bash #remove the MER.*_ in file name for all the files in a dir function getdir(){ for elemen ...

  5. MongoDB-2:MongoDB添加、删除、修改

    一.简介 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSQL数据库产品中最热门的一种.数据被分组存储在数据集中,被称为一个集合(Collenction)和对于存储在MongoDB ...

  6. 我的Android进阶之旅------>Android APP终极瘦身指南

    首先声明,下面文字转载于: APK瘦身实践 http://www.jayfeng.com/2015/12/29/APK%E7%98%A6%E8%BA%AB%E5%AE%9E%E8%B7%B5/ APP ...

  7. 初级学IP地址

    IP地址是我们上网的凭证!通过IP地址的学习.能够对网络拓扑结构有一个简单的认识,以及对网络的传递过程进行初步了解. 传输数据简单认识 网络中传播的数据是以数据包的形式存在的! 当中包括着目的IP地址 ...

  8. BeanUtils.copyProperties()

    BeanUtils.copyProperties() PropertyUtils.copyProperties() 通过反射将一个对象的值赋值个另外一个对象(前提是对象中属性的名字相同). 后付前 P ...

  9. tensorflow 的rnn的示例 ptb_word_lm.py 的完整代码

    其训练数据源在我的空间里,名字为:tensorflow的ptb-word-lm示例的训练数据源.tgz 讲解参见另一篇文章:  http://www.cnblogs.com/welhzh/p/6739 ...

  10. qt下通过socket传送中文

    zz 1.在main函数里我之前就加了一句QTextCodec::setCodecForTr( QTextCodec::codecForLocale() ); 现在再加一句QTextCodec::se ...