LeetCode刷题碎碎念(七):Linked List

单向链表

https://blog.csdn.net/haiyu94/article/details/79406082
单链表结构:
在这里插入图片描述

class Node:
    '''
    data: 节点保存的数据
    next: 保存下一个节点对象
    '''
    def __init__(self, data, _next=None):
        self.data = data
        self._next = _next

206. Reverse Linked List

1 -> 2 -> 3 -> 4 -> null 反向变成
null <- 1 <- 2 <- 3 <- 4

必须要知道一个node的current,previous,next结点是谁
起始:prev = null, curr = head

class Solution(object):
    def reverseList(self, head):
        prev = None
        curr = head
        while curr:
            # 反转
            nxt = curr.next	# 暂时存起来
            curr.next = prev	# 反向:本身是往后的指针改为向前指
            # 沿链表向前推进
            prev = curr
            curr = nxt
            
        return prev # 返回当前节点 因为prev = curr

92. Reverse Linked List II

在这里插入图片描述

class Solution:
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        dummy = ListNode(0)
        dummy.next = head
        prev = dummy
        # 因为这次交换不是从头开始,prev不是None,所以需要用dummy把prev引入前m的链表遍历中
        for i in range(m-1):
            prev = prev.next
            
        reverse = None  # 用来代替prev,因为prev后面要用
        curr = prev.next
        for i in range(n-m+1):  
            nxt = curr.next #  保存下一节点,因为curr.next马上就要变了
            curr.next = reverse
            reverse = curr
            curr = nxt
        
        # prev没有进入reverse的循环,所以是reverse前的那个node
        prev.next.next = curr   # reverse部分和后面重新连接
        prev.next = reverse     # reverse部分和前面重新连接
            
        return dummy.next   # listnode的第一个节点

21. Merge Two Sorted Lists (Easy)

  1. Recursion
    在这里插入图片描述
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        if not l1: return l2
        elif not l2: return l1
        
        elif l1.val < l2.val:
            l1.next = self.mergeTwoLists(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1, l2.next)
            return l2
  1. Iteration
    每次对 l1 和 l2 比较大小,小的放入prehead,并且next后移
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        prehead = ListNode(0)
        prev = prehead  # prev是指向当前append的最后一位的指针
        
        while l1 and l2:
            if l1.val <= l2.val:
                prev.next = l1
                l1 = l1.next
            else:
                prev.next = l2
                l2 = l2.next
            prev = prev.next

        if not l1:
            prev.next = l2
        elif not l2:
            prev.next = l1
        
        return prehead.next

24. Swap Nodes in Pairs (medium)

在这里插入图片描述

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        dummy = ListNode(0)
        dummy.next = head   # 链表的前一个位置的索引
        curr = dummy
        
        while curr.next and curr.next.next: # 有两个node可以交换
            first = curr.next
            second = curr.next.next
            
            curr.next = second          # curr链接后一个
            first.next = second.next    # 前一个链接后一个的下一个node(取代后一个的链接)
            second.next = first         # 后一个指向前一个
            curr = curr.next.next       # curr指针后移
        
        return dummy.next

2. Add Two Numbers (medium)

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        dummy = tail = ListNode(0)
        carry = 0
        while l1 or l2 or carry:
            v1 = v2 = 0
            if l1:
                v1 = l1.val
                l1 = l1.next
            if l2:
                v2 = l2.val
                l2 = l2.next
            
            carry, val = divmod(v1 + v2 + carry, 10)
            tail.next = ListNode(val)
            tail = tail.next
        return dummy.next

445. Add Two Numbers II

Combine reverseList and addTwoumbers

class Solution:
    def reverseList(self, head: ListNode):
        prev = None
        while head:
            nxt = head.next
            head.next = prev
            prev = head
            head = nxt
        return prev
    
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        l1 = self.reverseList(l1)
        l2 = self.reverseList(l2)
        
        dummy = tail = ListNode(0)
        carry = 0
        while l1 or l2 or carry:
            v1 = v2 = 0
            if l1:
                v1 = l1.val
                l1 = l1.next
            if l2:
                v2 = l2.val
                l2 = l2.next
            
            carry, val = divmod(v1 + v2 + carry, 10)
            tail.next = ListNode(val)
            tail = tail.next
        
        dummy = self.reverseList(dummy.next)
        return dummy

234. Palindrome Linked List (medium)

快慢指针

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        reverse = None
        slow = fast = head
        
        while fast and fast.next:
            fast = fast.next.next   # fast走到头
            
            nxt = slow.next           # slow走到中间,同时进行反转
            slow.next = reverse       # 完成对前半部分的反转
            reverse = slow
            slow = nxt
            
        if fast:
            slow = slow.next    # 中间往后一位,后半部分的第一位
            
        while reverse and reverse.val == slow.val:
            slow = slow.next
            reverse = reverse.next
            
        return not reverse

143. Reorder List (medium)

利用双指针,把链表分成前半部分和后半部分,然后后半部分reverse和前部部分合并。

1->2->3->4->5->6->7->8->None
前般+后半:
1->2->3->4->None
5->6->7->8->None
后半reverse:
1->2->3->4->None
8->7->6->5->None
合并

class Solution:
    def reorderList(self, head: ListNode) -> None:
        """
        Do not return anything, modify head in-place instead.
        """
        if not head: return 
        
        # slow是后半的第一个node
        # head是前半的第一个node
        slow = fast =  head
        while fast and fast.next:
            fast = fast.next.next
            slow  = slow.next
        
        # reverse后半段
        reverse = None
        curr = slow
        while curr:
            reverse, curr.next, curr = curr, reverse, curr.next
        
        # merge前半段和后半段
        first = head
        second = reverse
        while second.next:
            first.next, first = second, first.next
            second.next, second = first, second.next
        
        return 
reverse, curr.next, curr = curr, reverse, curr.next

==顺序是影响的!!!==不能先改变curr的值,这样curr.next也会同时发生变化。所以curr和curr.next先改变curr.next的值!

203. Remove Linked List Elements

要判断curr.next是否等于val,因为当前curr已经无法跳过了

class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        dummy = ListNode(0)
        dummy.next = head    
        curr = dummy
        while curr.next:
            if curr.next.val == val:
                curr.next = curr.next.next	# 跳过curr.next
            else:
                curr = curr.next
        
        return dummy.next

141. Linked List Cycle

判断是否有环:
利用快慢指针,如果两个指针会相遇(快指针先进入环内绕圈,之后遇见慢指针),那么有环;
如果两个指针不相遇,一直到fast.next == None,走到了头,没有环

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        fast = head
        slow = head
        while (fast != None and fast.next != None):
            slow = slow.next
            fast = fast.next.next
            
            if slow == fast:
                return True
        return False
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode *slow = head;
        ListNode *fast = head;
        
        while (fast && fast -> next)
        {
            slow = slow -> next;
            fast = fast -> next -> next;
            if (fast ==  slow)
            {
                return true;
            }
        }
        return false;
    }
};

142. Linked List Cycle II

链表中环的入口节点
https://www.cnblogs.com/hiddenfox/p/3408931.html
在这里插入图片描述
设:链表头是X,环的第一个节点是Y,slow和fast第一次的交点是Z。各段的长度分别是a,b,c,如图所示。环的长度是L。slow和fast的速度分别是qs,qf。
a == c

slow fast第一次交点z,然后让一个指针(cur)从起点开始走,每次一个next,因为a == c,所以slow从z走到y和cur从x走到花费相同步数,正好相交在y

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        slow = head
        fast = head
        
        while (fast and fast.next):
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                break
        else:
              return None
            
        cur = head;
        while (cur != slow):
            cur = cur.next
            slow = slow.next
        
        return cur
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *slow = head;
        ListNode *fast = head;
        bool flag = false;
        
        while (fast && fast -> next)
        {
            slow = slow -> next;
            fast = fast -> next -> next;
            if (fast == slow)
            {
                flag = true;
                break;
            }
        }
        
        if (!flag)
        {
            return NULL;
        }
        
        ListNode *cur = head;
        while (cur != slow)
        {
            cur = cur -> next;
            slow = slow -> next;
        }
        return cur;
    }
};

25. Reverse Nodes in k-Group (hard)

class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        if head == None or head.next == None:
            return head
        
        count = 0
        cur = head
        while cur != None and count != k:   # 前进k步
            cur = cur.next
            count += 1
        
        if count == k:
            cur = self.reverseKGroup(cur, k)    # 第一个k部分找到,递归处理后面的部分
            while count > 0:    # reverse linked list
                count -= 1
                temp = head.next
                head.next = cur
                cur = head
                head = temp
            head = cur
        
        return head

86. Partition List (Medium)

class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        # 用两个linked list分别储存大于等于x的和小于x的
        small = ListNode(0)
        cur1 = small
        big = ListNode(0)
        cur2 = big
        
        while head:
            tmp = ListNode(head.val)    # 只是要加入一个跟head的值一样的节点
                                        # 不要真的连到原始的linked list的head上
                                        # 会形成linked list 的环
            if head.val < x:
                cur1.next = tmp
                cur1 = cur1.next
            else:
                cur2.next = tmp
                cur2 = cur2.next
                
            head = head.next
            
        cur1.next = big.next    # 把大小两个linked list首尾相连
        return small.next

61. Rotate List

class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head or not head.next:
            return head
        
        index = head
        length = 1
        while index.next:   # 走到头
            index = index.next
            length += 1
            
        index.next = head   # index 为最后一个node,让他指向第一个node(head)
        for i in range(1, length - k % length): # 找到Linked List断开的恰当地方
            head = head.next                    # 同时解决rotate位数大于list长度
        
        res = head.next # 找到现在的第一个node(现在还是环),最后一个node的下一个node
        head.next = None    # 断开
        return res
        
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值