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

举报
毛利 发表于 2021/07/15 02:18:00 2021/07/15
1.5k+ 0 0
【摘要】 @Author:Runsen @Date:2020/9/13 链表是我这辈子的痛啊,每次学到链表,就往往不会,就没有继续学下去。现在大四不能继续让这个链表阻碍我了。现在基本是重刷数据结构和算法,毕竟笔试真的太重要了。 我又重温了争大佬专栏的栈,又巩固了下。 争哥专栏有一个非常的经典:就是关于指针的理解:将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或...

@Author:Runsen

@Date:2020/9/13

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

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

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

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

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

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

  
 

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

文章来源: maoli.blog.csdn.net,作者:刘润森!,版权归原作者所有,如需转载,请联系作者。

原文链接:maoli.blog.csdn.net/article/details/108560222

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。