LeeCode刷题(五)

转眼刷题已经是第五周了,由于平时上班,所以每周刷的题并不多,目前进展如下:
LeeCode刷题(五)_第1张图片
emmm,平均一周6,7到题。惭愧惭愧。不过这周做的时候看了一个刷题大佬总结的一些经验,下面是他GitHub的链接:https://github.com/liweiwei1419
里面有他刷题的一些经验总结心得。我觉的对刚开始刷题的人来说还是挺有帮助的。就比如我一开始的打算是把热题中的简单难度的都刷完,然后再中等,困难。虽然之前几周也都有总结,但是效果感觉不是很好,比如简单做过的题,中等的遇到类似了还是有点束手无措的感觉。看了大佬的经验后,我感觉按模块来刷题的方法或许会更好一点。
以下是大佬在GitHub中总结的一些刷题建议,我这里转载一下作为自己的参考:

  • 先学习,有一些预备知识以后,再做题
    有些算法题做不出来很正常,那是因为自己的知识储备还不够。所以要么看书、看视频学习,要么就把这个不会做的问题当做知识点进行学习。一开始抄代码我觉得都是可以的,抄完代码要删掉了以后,自己再写几遍。实在想了很久还想不出来的问题,就看题解和别人的视频学习哈。

  • 要多做几遍,尝试做总结和分类
    一道题,特别是经典的问题,要尝试多做几遍,作总结。有些问题的思想是通用的,而且技巧也是相对固定的,需要不断练习巩固和体会。

  • 尝试一题多解,不要忽视暴力解法
    一题多解,有些时候就相当于做了几遍了。“暴力解法”通常是进阶解法的基础,由“暴力解法”开始分析缺点,然后改进和优化,去理解这道题的解法通常是很自然的。

  • 尝试输出,分享出去
    较多程序员(包括我本人)相对欠缺的能力是语言表达和书面表达。而输出就是一个比较好的锻炼自己的方式,写博客写题解可以帮助到别人,也可以帮助自己整理思路,还可以交朋友。

  • 参加竞赛,练手
    前面的题目可能就像课后练习一样,你做不做它就在那里,就有那么多,还可以看答案,做起来没什么动力。想模拟面试和笔试的感觉,就可以参加竞赛。

-----------------------------------------------------------分割线------------------------------------------------------------------------

本周刷了几道排序的题目,其中删除链表的倒数第N个节点一题如果我们转化下思维把题目改成删除链表中第(L - n + 1)个结点,即正数链表长度L-倒数n+1个节点,就会比较容易理解和解决了。
还有颜色分类一题,题解中也提到本题也可以称为是荷兰国旗问题。由于只有三种数字,所以要对这三种数字进行排序的时候我们就可以分类讨论。
该题代码如下:

    public void sortColors(int[] nums) {
     
        int start = 0;
        int end = nums.length - 1;
        int curr = 0;
        int tmp = 0;
            while (curr <= end) {
     
            // 如果当前节点等于0,则起始节点的值和当前节点值互换,起始节点和当前节点都右移
            // 如果当前节点等于2,则末尾节点的值和当前节点值互换,由于互换后当前节点的值不确定,因此只进行末节点左移,当前节点不动,等待下一次循环判断其值
            // 如果当前节点等于1,则当前节点向右移,始末节点位置不变
            if (nums[curr] == 0) {
     
                tmp = nums[start];
                nums[start] = nums[curr];
                nums[curr] = tmp;
                start++;
                curr++;
            } else if (nums[curr] == 2) {
     
                tmp = nums[end];
                nums[end] = nums[curr];
                nums[curr] = tmp;
                end--;
            }else {
     
                curr++;
            }

        }
    }

还有一道排序链表的题目。这道题使用归并排序的方法可以很好的实现。可以采用自顶向下的分裂后归并,也可以采用自底向上的归并排序。其原理其实是一样的。这里以自顶向下的分裂归并方法为例说明。对于两个元素之间的排序相信大家都会,所以我们只要将给定的链表拆分成一个个小的链表,知道都是单独的数字之后,这个时候我们再对其进行两两归并,最终归并后的结果就是最终的排序后的链表。
下面贴上一个大佬的代码,他就是把之前做过的题目中的方法套到这里之和很好的解决了这道题:

   public ListNode sortList(ListNode head) {
     
        // 1、递归结束条件
        if (head == null || head.next == null) {
     
            return head;
        }

        // 2、找到链表中间节点并断开链表 & 递归下探
        ListNode midNode = middleNode(head);
        ListNode rightHead = midNode.next;
        midNode.next = null;

        ListNode left = sortList(head);
        ListNode right = sortList(rightHead);

        // 3、当前层业务操作(合并有序链表)
        return mergeTwoLists(left, right);
    }

    //  找到链表中间节点(876. 链表的中间结点)
    private ListNode middleNode(ListNode head) {
     
        if (head == null || head.next == null) {
     
            return head;
        }
        ListNode slow = head;
        ListNode fast = head.next.next;

        while (fast != null && fast.next != null) {
     
            slow = slow.next;
            fast = fast.next.next;
        }

        return slow;
    }

    // 合并两个有序链表(21. 合并两个有序链表)
    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
     
        ListNode sentry = new ListNode(-1);
        ListNode curr = sentry;

        while(l1 != null && l2 != null) {
     
            if(l1.val < l2.val) {
     
                curr.next = l1;
                l1 = l1.next;
            } else {
     
                curr.next = l2;
                l2 = l2.next;
            }

            curr = curr.next;
        }

        curr.next = l1 != null ? l1 : l2;
        return sentry.next;

    }

你可能感兴趣的:(LeetCode,java,算法)