【每日三题】删除有序链表的重复元素,分割链表

132 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情 >>


每日三刷,剑指千题

计划简介:

  • 每日三题,以中等题为主,简单题为辅进行搭配。保证质量题1道,数量题3道。
  • 每日早通勤在LeetCode手机端选题,思考思路,没答案的直接看题解。
  • 每日中午进行编码,时间控制在一小时之内。
  • 下班前半小时进行整理总结,并发布到掘金每日更文活动。

说明:

  • 基于以前的刷题基础,本次计划以中等题为主,大部分中等题都可以拆分为多个简单题,所以数量保证3,质量保证一道中等题即可。
  • 刷题顺序按照先刷链表、二叉树、栈、堆、队列等基本数据结构,再刷递归、二分法、排序、双指针等基础算法,最后是动态规划、贪心、回溯、搜索等复杂算法。
  • 刷题过程中整理相似题型,刷题模板。
  • 目前进度 114/1000

[82] 删除排序链表中的重复元素 II

给定一个已排序的链表的头 head删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表

示例 1:

img

输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]

解析

四指针是为了夺人眼球,其核心思想依然是双指针,滑动窗口,只不过为了删除操作,需要维护前一个结点。

注意如果是[1,2,3,3,3] 这种 3 是删不掉的,所以循环完判断一下是否还有未删除的,再做一次删除。

Code

class Solution {
        public ListNode deleteDuplicates(ListNode head) {
            if (head == null) return null;
            ListNode dummy = new ListNode(-1000,head);
            ListNode prev = dummy;
            ListNode delEnd = null;
            ListNode delStart= new ListNode(-100,dummy);
            while (head!=null){
                if (head.val==prev.val){
                    // 窗口有边界后移
                    delEnd = head;
                }else {
                    if (delEnd!=null){
                        // 删除
                        delStart.next = delEnd.next;
                        prev = delStart.next;
                        // 这里一定要置null,最后才能判断是否有没删除的
                        delEnd = null;
                    }else {
                        prev = prev.next;
                        // 窗口左边界前移
                        delStart = delStart.next;
                    }
​
                }
                head = head.next;
            }
            if (delEnd != null){
                delStart.next = null;
            }
            return dummy.next;
        }
    }

[86]分隔链表

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例 1:

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

解析

迭代法,正常的去遍历,小于特定值的拼接在一个链表就后面,大于等于特定值的拼接在两一个链表后面。最后把两个链表拼在一起就行。空间利用率不高。

我觉得如果把链表换成数组,这道题就会是简单题了。

Code

class Solution {
        public ListNode partition(ListNode head, int x) {
            if (head==null)return null;
            ListNode small = new ListNode(0);
            ListNode big = new ListNode(0);
            ListNode dummyBig = big;
            ListNode dummySmall= small;
​
            while (head != null) {
                if (head.val < x){
                    small.next = head;
                    head = head.next;
                    small.next.next=null;
                    small = small.next;
                } else {
                    big.next = head;
​
                    head = head.next;
                    big.next.next = null;
                    big = big.next;
                }
            }
            small.next = dummyBig.next;
            return dummySmall.next;
        }
    }

[剑指 Offer 25]合并两个排序的链表

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

示例1:

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

解析

做过的一道题,复习一下,类似的还有 合并两个有序数组。

Code

    class Solution {
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            ListNode ans = new ListNode(0);
            ListNode dummy = ans;
            while (l1 != null && l2 != null) {
                if (l1.val < l2.val) {
                    ans.next = l1;
                    l1 = l1.next;
                } else {
                    ans.next = l2;
                    l2 = l2.next;
                }
                ans = ans.next;
            }
            ans.next = l1 == null ? l2 : l1;
            return dummy.next;
        }
    }

\