分类刷题:链表的删除

删除链表中重复的结点

https://www.nowcoder.com/practice/fc533c45b73a41b0b44ccba763f866ef?tpId=265&rp=1&ru=%2Fexam%2Foj%2Fta&qru=%2Fexam%2Foj%2Fta&sourceUrl=%2Fexam%2Foj%2Fta%3FtpId%3D13&difficulty=&judgeStatus=&tags=&title=&gioEnter=menu

分类编程打卡第1天:

JZ18 删除链表的节点

    def deleteNode(self , head: ListNode, val: int) -> ListNode:
        #加入一个头节点
        res = ListNode(0)
        #将头节点挂靠到原始头节点
        res.next = head
        #如果不定义这个让pre去操作,最后输出res将是一个数字(即node.val)
        #指针移动了,不开一个,无法找到链表头返回
        pre = res
        #其实这一步可以省略,因为最后输出的是pre相关的res
        cur = head
        while cur:
            if cur.val == val:
                pre.next = cur.next
            pre = cur
            cur = cur.next
        return res.next

Leetcode83. 删除排序链表中的重复元素

题目描述:

输入:head = [1,1,2] 输出:[1,2]

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

直接遍历

    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head:
            return None
        cur = head
        while cur.next:
            if cur.val == cur.next.val:#判断当前位置是否为重复数据
                cur.next = cur.next.next#如果是的话探索之后的数据是否为相同的数据
            else:
                cur = cur.next#如果当前位置非重复数据就下一个
        return head

快慢指针

    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head:
            return None
        slow = fast = head
        while fast:
            if slow.val != fast.val:
                slow.next = fast
                slow = slow.next #slow后移
            fast = fast.next #fast后移
        slow.next = None
        return head

JZ76 删除链表中重复的结点

题目描述:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5

注意:链表已被排序,所以若有重复节点则是至少两个连续的

方法1:直接比较删除法

    def deleteDuplication(self , pHead: ListNode) -> ListNode:
        #空链表
        if pHead == None: 
            return None
        res = ListNode(0)
        #在链表前加一个表头
        res.next = pHead 
        cur = res
        while cur.next and cur.next.next:  #要从cur.next开始是因为cur.next才是pHead,只有这样才能从头遍历
            #遇到相邻两个节点值相同
            if cur.next.val == cur.next.next.val: 
                temp = cur.next.val
                #将所有相同的都跳过,因为cur.next = cur.next.next指针不断地往后移所以是有可能让cur.next = None的,所以要避免这种情况发生
                while cur.next != None and cur.next.val == temp: 
                    cur.next = cur.next.next
            else:
                cur = cur.next
        #返回时去掉表头
        return res.next

注意:

这一题与Leetcode83. 删除排序链表中的重复元素很类似,不同点在于本题要把重复的元素删干净,而Leetcode要保留一个。

下面系统的重新看一遍三种类型的不同点:

1. 删干净:(自己复现的过程)

第一遍自己写:首先参考了83的代码:

    def deleteDuplication(self , pHead: ListNode) -> ListNode
        if pHead == None: 
            return None
        cur = pHead 
        while cur.next: 
            if cur.val == cur.next.val: 
                temp = cur.val
                while cur.next != None and cur.next.val == temp: 
                    cur.next = cur.next.next
            else:
                cur = cur.next
        return pHead

输出的结果并没有把重复元素全部删干净,原因在于比如[1,2,2,3,4,5]在遍历到第一个2的时候,cur=2, cur.next=2, temp=2, cur.next将跳到3,而返回if判断语句发现2!=3,所以跳到else判断语句,继续保留2。以至于最后的输出实际上是原来的pHead。

第二遍修正:

    def deleteDuplication(self , pHead: ListNode) -> ListNode:
        #空链  
        if pHead == None: 
            return None
        res = ListNode(0)
        res.next = pHead
        cur = res 
        while cur.next and cur.next.next: 
            if cur.next.val == cur.next.next.val: 
                temp = cur.next.val
                while cur.next != None and cur.next.val == temp: 
                    cur.next = cur.next.next
            else:
                cur = cur.next
        return res.next

注意:继续以[1,2,2,3,4,5]为例,在遍历到1的时候就已经开始判断2和2是否相等了,2=2,temp=2,继续向后遍历,只要没到最后,且还有重复元素,接着因为cur.next已经调到了第二个2,依然满足2=temp,所以cur.next跳到了3,不再满足while条件,故推出进入else,所以把3给保存上了。

核心在于可以把cur.next剥离出来作为一个单独的考虑因素去进行处理,那么就不会影响到cur

更好理解的解法3:

    def deleteDuplication(self , pHead: ListNode) -> ListNode:
        # 定义头节点指针,前指针和当前指针
        p0 = ListNode(-1)
        p0.next = pHead
        p = p0 
        cur = pHead
        # 循环遍历
        while cur and cur.next:
            # 不相等,则前后指针继续遍历
            if cur.val != cur.next.val:
                p = p.next
                cur = cur.next
            else:
                # 出现重复节点,即当前指针节点与下一个节点相等,则cur继续向右判断
                val = cur.val
                while cur and cur.val == val:
                    cur = cur.next
                p.next = cur
        return p0.next

2. 只剩1个:

直接遍历

    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head:
            return None
        cur = head
        while cur.next:
            if cur.val == cur.next.val:#判断当前位置是否为重复数据
                cur.next = cur.next.next#如果是的话探索之后的数据是否为相同的数据
            else:
                cur = cur.next#如果当前位置非重复数据就下一个
        return head

方法2: 哈希表

    def deleteDuplication(self , pHead: ListNode) -> ListNode:
        #空链表
        if pHead == None: 
            return None
        mp = dict()
        cur = pHead
        #遍历链表统计每个节点值出现的次数
        while cur: 
            if cur.val in mp:
                mp[cur.val] += 1
            else:
                mp[cur.val] = 1
            cur = cur.next
        res = ListNode(0)
        #在链表前加一个表头
        res.next = pHead 
        cur = res
        #再次遍历链表
        while cur.next: 
            #如果节点值计数不为1
            if mp[cur.next.val] != 1: 
                #删去该节点
                cur.next = cur.next.next 
            else:
                cur = cur.next
        #去掉表头
        return res.next 

注意:要熟练掌握构建哈希表的方法

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务