Leetcode刷题之链表篇(一)

链表篇

06. 从尾到头打印链表

  • 思路1:直接遍历链表,存到数组后,利用数组逆序即可
  • 思路2:链表+逆序 自然想到使用递归
#思路1:遍历
class Solution(object):
    def reversePrint(self, head):
        nums = []
        while(head):
            nums.append(head.val)
            head = head.next
        return nums[::-1]
#思路2:递归
class Solution:
    def __init__(self):
        self.nums = []
    def reversePrint(self, head):
        self.my_reverse(head)
        return self.nums
    def my_reverse(self,head):
        if(not head): return 
        self.my_reverse(head.next)
        self.nums.append(head.val)

总结:对于链表和二叉树类型的题目,可以采取递归(费空间)的方式,特别是题目出现逆序的情况下。

206. 反转链表

  • 思路1:迭代写法,利用pre、cur双指针完成反转
  • 思路2:链表+逆序 自然想到使用递归
# 迭代
class Solution(object):
    def reverseList(self, head):
        pre,cur = None,head
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        return pre
# 递归
class Solution(object):
    def reverseList(self, head):
        if not head or not head.next: return head
        ret = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return ret

总结:链表经常采取双指针pre、cur

92. 反转链表II

  • 思路1:引入哨兵节点,然后记录left的前一个节点和right的下一个节点,对left和right之间的节点进行局部反转
# 迭代
class Solution(object):
    def reverseBetween(self, head, left, right):
        auxi = ListNode(0,head)
        cnt = 0
        pre,cur = auxi,head
        start,end,start2 = None,None,None
        while cur:
            cnt += 1 
            if cnt > right: break
            tmp = cur.next
            if cnt >= left:
                if cnt == right: end = tmp
                if cnt ==left: 
                    start = pre
                    start2 = cur
                elif cnt>left and cnt <= right:
                    cur.next = pre                
            pre = cur
            cur = tmp
        start.next = pre
        start2.next = tmp
        return auxi.next

总结:头节点不确定,通常引入哨兵节点

234. 回文链表

  • 思路1:快慢指针对链表二分,然后对链表后半部分采取反转链表,最后一一比较
  • 思路2:用额外数组记录链表节点值,然后判断回文数组
  • 思路3:回文链表涉及到逆序,可以考虑递归(费空间)
# 链表二分
class Solution(object):
    def isPalindrome(self, head):
        fast,slow = head,head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        pre,cur = None,slow
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        while pre and head:
            if pre.val!=head.val:
                return False
            pre = pre.next
            head = head.next
        return True
# 额外数组
class Solution(object):
    def isPalindrome(self, head):
        ret = []
        while head:
            ret.append(head.val)
            head = head.next
        return ret == ret[::-1]
# 递归
class Solution(object):
    def __init__(self):
        self.cur = None
    def isPalindrome(self, head):
        self.cur = head
        return self.dfs(head)
    def dfs(self,head):
        if not head: return True
        a = self.dfs(head.next)
        if self.cur.val == head.val:
            self.cur = self.cur.next
            return a
        return False

总结:链表题目涉及到 前半部分和后半部分概念时,采取快慢指针对链表进行二分(回文链表、链表归并排序、重排链表都有这个思想)

18. 删除链表的节点

  • 思路1:引入哨兵节点,采取双指针pre、cur分别记录待删除节点的前一个节点和待删除节点
class Solution(object):
    def deleteNode(self, head, val):
        ret = ListNode(0)
        ret.next = head
        pre,cur = ret,head
        while cur.val!=val:
            pre = cur
            cur = cur.next
        pre.next = cur.next
        return ret.next

总结:头结点不确定时,可引入哨兵节点

237. 删除链表中的节点

  • 思路1:把下一个节点的值拷贝到当前节点,然后删除下一个节点
class Solution(object):
    def deleteNode(self, node):
        node.val = node.next.val
        node.next = node.next.next

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

  • 思路1:如果cur和cur.next值一样,就持续删除,否则更新cur
class Solution(object):
    def deleteDuplicates(self, head):
        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

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

  • 思路1:引入哨兵节点,采取pre、cur双指针,借助flag标志位来判断哪些节点需要删除
  • 思路2:引入哨兵节点,采取pre、cur双指针,只要相邻节点值一样,就用while循环找到相邻节点不一样的位置,然后再考虑更新pre、cur
# 思路一
class Solution(object):
    def deleteDuplicates(self, head):
        if not head or not head.next: return head
        auxi = ListNode(0,next=head)
        pre,cur = auxi,head
        flag = False
        while cur and cur.next:
            if cur.val == cur.next.val:
                cur = cur.next
                flag = True
            else:
                if flag:
                    flag = False
                    cur = cur.next
                else:
                    pre.next = cur
                    pre = cur
                    cur = cur.next
        if flag: pre.next = cur.next
        else: pre.next = cur
        return auxi.next
# 思路二
class Solution(object):
    def deleteDuplicates(self, head):
        if not head or not head.next: return head
        auxi = ListNode(0,next=head)
        pre,cur = auxi,head
        while cur and cur.next:
            if cur.val == cur.next.val:
                while cur.next and cur.val==cur.next.val:
                    cur = cur.next
                cur = cur.next
                pre.next = cur
            else:
                pre = cur
                cur = cur.next
        return auxi.next

总结:头结点不确定时,可引入哨兵节点

203. 移除链表元素

  • 思路1:引入哨兵节点,采取pre、cur,根据cur值是否等于val来更新pre、cur
class Solution(object):
    def removeElements(self, head, val):
        auxi = ListNode(0,next=head)
        pre,cur = auxi,head
        while cur:
            tmp = cur.next
            if cur.val == val:
                pre.next = tmp
            else:
                pre = cur
            cur = tmp
        return auxi.next

总结:头结点不确定时,可引入哨兵节点

160. 相交链表

  • 思路1:利用双指针以及两个链表的长度之和是固定的
  • 思路2:集合记录访问过的节点,如果重复则相交
# 双指针
class Solution(object):
    def getIntersectionNode(self, headA, headB):
        cur1,cur2 = headA,headB
        while(cur1!=cur2):
            cur1 = cur1.next if cur1 else headB
            cur2 = cur2.next if cur2 else headA
        return cur1
 # hash额外空间
 class Solution(object):
    def getIntersectionNode(self, headA, headB):
        mySet = set()
        cur = headA
        while cur:
            mySet.add(cur)
            cur = cur.next
        cur = headB
        while cur:
            if cur in mySet: return cur
            cur = cur.next
        return None
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值