刷leetCode算法题+解析(四)

合并两个有序链表

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

示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

这个要多讲讲,因为完全涉及到了我的知识盲区!!!有序链表这种东西真的没怎么接触过,树也接触的少,毕竟我就是一个非科班,在小外包公司成长起来的,一直以来对这种数据结构还有算法什么的保有憧憬和向往(这也是现在刷算法的原因)。刚一接触题目,这个ListNode都够让我看好久了,就是不明白为啥next就是下一个节点。还是我狗群友给了我指点,在此表示感谢。步入正题。
思路:我自己做的麻烦了,因为是先把两个链表取出来排序然後在放到一个链表了,看了大佬思路才发现可以两个链表取出来直接放到链表里,省去了中间的过程。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1==null && l2==null){
            return new ListNode(0).next;
        }
        //遍历俩链表,元素都取出来
        List<Integer> list = new ArrayList<Integer>();
        while(l1!=null){
            list.add(l1.val);
            l1=l1.next;
        }
        while(l2!=null){
            list.add(l2.val);
            l2=l2.next;
        }   
        //为了保证链表的有序性,所以把list排序     
        Collections.sort(list);
        //保存头节点
        ListNode result = new ListNode(0);
        //用cur来控制指针往下挂节点?
        ListNode cur = result;
        for(Integer i:list){
            cur.next = new ListNode(i);
            cur = cur.next;
        }
        return result.next;
    }
}

这个其实不夸张的说真的是一道题卡半天,因为关于链表,节点什么的没什么意识,差不多做点就问群里人,然後现在为止也不能说多了解链表吧。但是勉强上面的代码可以解释的通,理解面上的意思了(我不知道我注解是不是错了,如果错了欢迎指出)。
然後我都做完了,甚至哪怕看了大神的解法开始分析了,还是在群友的提醒下发现了问题:题目要求是要拼接两个链表节点,我这里取了巧,用的list排序。所以下面老老实实介绍大神的写法


题目

其实大神的写法思路也很清晰,如果懂了链表的结构也很简单就能看懂。我反正现在是勉勉强强可以写出来。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        //定义好头节点
        ListNode result = new ListNode(0);
        //用这个cur来挂载节点
        ListNode cur = result;
        //两个链表都不为空才有必要比较,只剩一个了直接全挂上就好了
        while(l1!=null && l2!=null){
            //因为要按照顺序挂,所以先挂小的
            if(l1.val<l2.val){
                //因为头结点0.所以往下挂
                cur.next = l1;
                l1 = l1.next;
                cur = cur.next;
            }else{
                cur.next = l2;
                l2 = l2.next;
                cur = cur.next;
            }
        }
        if(l1!=null){
            cur.next = l1;
        }else{
            cur.next = l2;
        }
        //cur的指针已经指到最后了,所以只能从result开始,头节点那个0是自己加的,所以不算,从头节点的下一个开始
        return result.next;
    }
}

删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
你不需要考虑数组中超出新长度后面的元素。

思路:这个题目其实挺唬人的,什么不使用额外的数组空间,就是不能创建新数组呗。O(1)这个概念还是我现去百度的
O(1):就是最低的时空复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。 哈希算法就是典型的O(1)时间复杂度,无论数据规模多大,都可以在一次计算后找到目标(不考虑冲突的话)
但是抛除了这几句话开始正常考虑思路其实也没那么难。不就是要做到两点:一使数组中没有重复元素,二返回数组长度么。首先不能创建新数组,所以只能在原数组中改动,其次因为是有序数组,最多就是一样的数组连续排在一起,不会存在隔过一个跟之前的相同,所以只要比较上一个元素就行而不是要遍历比较之前所有的元素。
接下来就是实现的代码:

    public int removeDuplicates(int[] nums) {
        //打标
        int j = 0;
        int i = 1;
        while(i<nums.length){
            //初始i=1,j=0.两个值相等说明重复了
            if(nums[j]==nums[i]){
                i++;   
            //两个值不相等才算是增加一个数组中元素个数    
            }else{
                j++;
                nums[j] = nums[i];
                i++;
            }
        }
        return nums.length==0?0:j+1;        
    }

然后因为这个理清楚逻辑是很好写出来的,说句题外话,我最近用了LeetCode才深感编译器的重要性。无论是自动提示还是报错提醒都特别有用。因为用LeetCode经常遇到忘记加标点符号或者后半个括号什么的,还非要运行才报错,麻烦死了。
上面的代码一开始我用的for循环,跑出了两次数组下标越界才改成现在这个版本的!
然后贼自豪的是跑出来的用时超过了百分百的用户,第一次哎!


image.png

上面代码中用了两个标:一个j是数组的下标、我们都知道数组的元素数是下标+1.因为下标从0开始。一个是原数组中的下标i。这个只是为了判断是否还有元素没有比较到。等到数组中所有元素比较完了,把唯一出现的存进去,重复出现的不用管了反正不占位就放那放着,占位了的就用新的把老的替换了。
之前看了下大神的解析,差不多都是用的这种思路。只不过细节上可能是略有不同,有的for循环有的do-while也有的和我一样是while。
然后好像这种思路有一个专有名词,叫做双指针解法?反正思路是大同小异,所以我也不多说了。

移除元素

题目:给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:
给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,1,2,2,3,0,4,2], val = 2,
函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
注意这五个元素可为任意顺序。
你不需要考虑数组中超出新长度后面的元素。

这个题目其实只要是上道题会做了这个也自然会做了。只不过上题判断的是重复,这个题判断的是等于某值而已。不多说了,上代码:

    public int removeElement(int[] nums, int val) {
        //打标,作为原数组下标
        int i = 0;
        //打标,作为现在的数组下标
        int j = 0;
        //原数组下标不越界就ok,所以这里用j<nums.length做条件
        while(i<nums.length){
            //从第一个元素开始判断是否为val,如果是则将这个元素替换成下一个元素再判断
            if(nums[i]==val){                
                i++;                        
            }else{               
                nums[j] = nums[i];
                i++;
                j++; 
            }
        }    
        return j;       
    }

这个题没什么可解释的了,除了那个if条件剩下一样一样的代码。不过这个是从第0个开始判断,上一个因为判重,所以第一个元素肯定不会重复,所以是从第一个开始判断。

今天因为一些工作的原因,还有链表耽误了很多时间,所以几天就这三道题,如果稍微帮助到了你点个喜欢点个关注,也祝大家工作顺顺利利!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,728评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,220评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 171,936评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,976评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,981评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,468评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,843评论 3 428
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,817评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,353评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,384评论 3 346
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,510评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,113评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,833评论 3 338
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,290评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,419评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,055评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,577评论 2 365