为了OFFER,花了几个小时,刷下Leetcode链表算法题

@Author:Runsen

@Date:2020/9/13

链表是我这辈子的痛啊,每次学到链表,就往往不会,就没有继续学下去。现在大四不能继续让这个链表阻碍我了。现在基本是重刷数据结构和算法,毕竟笔试真的太重要了。 我又重温了争大佬专栏的栈,又巩固了下。

争哥专栏有一个非常的经典:就是关于指针的理解:将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量。

涉及到链表的操作,重新看了专栏,一定要在纸上把过程先画出来,再写程序。对于链表其实基本就是单链表,很少是双链表,或者循环链表的题目

为了OFFER,花了几个小时,刷下Leetcode链表算法题_第1张图片

由于一个节点只通过next指针保存了它的下一个节点,失去了它的前驱节点信息,而且单链表数据结构通常长度未知,因此几乎所有单链表题目都是在前驱节点和长度上做文章。
常见链表面试算法,可以使用双指针迭代的方式以及递归的方式。

下面就是我2020/9/13 在leetcode 刷的链表题目,很多注释都写清楚了。关于题目的描述,这里不直接抄Leetcode 了。

文章目录

  • LeetCode206 反转一个单链表
  • Leetcode 第二题 addTwoNumbers
  • 剑指 Offer 18. 删除链表的节点
  • 面试题 02.03删除中间节点
  • 面试题 02.01. 移除重复节点
  • 面试题 02.06 回文链表
  • Leetcode 143. 重排链表
  • 剑指 Offer 22. 链表中倒数第k个节点
  • Leetcode19. 删除链表的倒数第N个节点

LeetCode206 反转一个单链表

这个反转单链表,写了N次,但又写的时候,又写不出来。服了,自己。看似,简单,博客最起码写了3次 反转一个单链表

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        prev = None
        cur = head
        while cur:
        	# prev 指cur.next cur指prev cur.next指cur
            cur.next,prev,cur = prev,cur,cur.next
        return prev

Leetcode 第二题 addTwoNumbers

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        # 将l1链表的数取出,组成一个数,l2同理,最终求和,将求和结果循环得出每个节点的值,然后链表连接即可!!!
        # 将链表转化列表
        val1, val2 = [l1.val], [l2.val]
        print(val1) #[2]
        print(val2) #[5]
        while l1.next:
            val1.append(l1.next.val)
            l1 = l1.next

        while l2.next:
            val2.append(l2.next.val)
            l2 = l2.next

        print(val1) #[2, 4, 3]
        print(val2) #[5, 6, 4]
        # 反转列表 用join方法拼接数字 切片[::-1]

        num_1 = ''.join([str(i) for i in val1[::-1]])
        num_2 = ''.join([str(i) for i in val2[::-1]])

        sums =  str(int(num_1) + int(num_2))[::-1]  # 708
        
        # 将sum转化成链表res

        # 头节点
        res  = head = ListNode(int(sums[0]))

        for i in range(1, len(sums)):
            # 拼接
            head.next = ListNode(int(sums[i]))
            head = head.next
        return res

剑指 Offer 18. 删除链表的节点

class Solution:
    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        # 如果头结点为空,直接返回
        if not head:
            return head
        # 如果头结点值等于val,直接返回head.next(题设中有注明链表中元素不重复)
        if  head.val == val:
            return head.next
        # 定义一个指针
        cur = head
        while cur.next:
            # 关键步骤,如果next的值等于val,跳过该节点
            if cur.next.val == val:
                cur.next = cur.next.next
                break
            cur = cur.next
        return head

面试题 02.03删除中间节点

# 将要删除节点的 val 赋值为下一结点的 val
node.val = node.next.val
# 然后将要删除节点的下一结点指向要删除节点的下一结点的下一结点
node.next = node.next.next

面试题 02.01. 移除重复节点

class Solution:
    def removeDuplicateNodes(self, head: ListNode) -> ListNode:
        # 如果没有head,那么直接return
        if not head: return 
        # 用集合来储存起来
        visited = {
     head.val}
        cur = head
        # 处理当前节点的下一个节点
        while cur and cur.next:
            # 如果当前的val在字典中,那么直接不要 
            if cur.next.val in visited:
                cur.next = cur.next.next
            else:
                # 集合的add 直接加入 集合或者元组都可以
                visited.add(cur.next.val)
                # 往下遍历
                cur = cur.next
        return head

面试题 02.06 回文链表

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
    	# 链表转化为列表,判断是不是  回文
        res = []
        cur = head
        while cur:
            res.append(cur.val)
            cur = cur.next
        # print(res)
        if res[::-1] == res:
            return True
        else:
            return False

Leetcode 143. 重排链表

class Solution:
    '''
    @Author :Runsen
    给定链表 1->2->3->4, 重新排列为 1->4->2->3.
    给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.
    就是每次取两边,先左到右 

    1 -> 2 -> 3 -> 4 -> 5 -> 6
    第一步,将链表平均分成两半
    1 -> 2 -> 3
    4 -> 5 -> 6
        
    第二步,将第二个链表逆序
    1 -> 2 -> 3
    6 -> 5 -> 4
        
    第三步,依次连接两个链表
    1 -> 6 -> 2 -> 5 -> 3 -> 4

    1 -> 2 -> 3 -> 4 -> 5 -> 6
    '''
    # 思路 找到中间节点,然后将右面的翻转,先定义一个翻转函数,Leetcode 206
    def reverseList(self, head):
        pre = None
        cur = head
        while cur:
            cur.next, pre, cur = pre, cur, cur.next
        return pre


    def reorderList(self, head: ListNode) -> None:
        """
        Do not return anything, modify head in-place instead.
        """
        if not head:
            return head
        slow, fast = head, head
        while fast and fast.next:
            slow, fast = slow.next, fast.next.next
        # 寻找中间节点 快慢指针中的慢指针就是中间节点
        p = slow.next
        slow.next = None
        p = self.reverseList(p)
        # 这个时候的p就是链表右面的翻转
        m = head
        while p:
            # 怎么拼接?
            # m ,m.next, p, p.next  => p, m.next, m.next, p.next  返回的是m这个链表
            m.next, p.next, m, p = p, m.next, m.next, p.next


剑指 Offer 22. 链表中倒数第k个节点

最常规的方法就是将链表变成数组,直接一个索引取值就可以了。

class Solution:
    def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
        res = []
        while head:
            res.append(head)
            head = head.next
        return res[-k]

有的大佬给出快慢指针的方法,就是快指针先走 K 步,然后再快慢指针一起走,当快指针跑出来时,慢指针的就是倒数第k个节点。

class Solution:
    def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
        former, latter = head, head
        for _ in range(k):
            former = former.next
        while former:
            former, latter = former.next, latter.next
        return latter

参考:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/solution/mian-shi-ti-22-lian-biao-zhong-dao-shu-di-kge-j-11/

Leetcode19. 删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

这题和上面那题是一样的,都是快慢指针,只不过这里需要返回链表的头结点。那定义一个Node = ListNode(None)就可以了。

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        # 快慢指针
        Node = ListNode(None)
        Node.next = head
        first,slow = Node,Node
        for i in range(n):
            first = first.next
        while first.next != None:
            first = first.next
            slow = slow.next
        slow.next = slow.next.next
        return Node.next

为了OFFER,花了几个小时,刷下Leetcode链表算法题_第2张图片

不知不觉现在到了下午三点,从早上九点半到现在,刷了九题的链表算法题目,真心累!!!!

你可能感兴趣的:(链表,算法)