三、基础算法精讲:链表-反转系列

目录

  • 1、反转链表
  • 2、反转链表 II
  • 3、K 个一组翻转链表
  • 4、两两交换链表中的节点
  • 5、两数相加 II
  • 6、翻倍以链表形式表示的数字

1、反转链表

Leetcode 206

python 中,参数注解 optional[ListNode] 的含义是:head 参数的类型可以是 ListNode 或者 None

class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        pre = None
        cur = head
        while cur:
            nxt = cur.next
            cur.next = pre
            pre = cur
            cur = nxt
        return pre
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *pre = nullptr, *cur = head;
        while (cur) {
            ListNode* nxt = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nxt;
        }
        return pre;
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

2、反转链表 II

Leetcode 92

class Solution:
    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        p0 = dummy = ListNode(next=head)
        for _ in range(left - 1):
            p0 = p0.next
        pre, cur = None, p0.next
        for _ in range(right - left + 1):
            nxt = cur.next
            cur.next = pre
            pre = cur
            cur = nxt
        p0.next.next = cur
        p0.next = pre
        return dummy.next
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        ListNode *dummy = new ListNode(0, head), *p0 = dummy;
        for (int i = 0; i < left - 1; i ++ ) p0 = p0->next;
        ListNode *pre = nullptr, *cur = p0->next;
        for (int i = 0; i < right - left + 1; i ++ ) {
            ListNode *nxt = cur->next;
            cur->next = pre;
            pre = cur, cur = nxt;
        }
        p0->next->next = cur, p0->next = pre;
        return dummy->next;
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

3、K 个一组翻转链表

Leetcode 25

class Solution:
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        n = 0
        cur = head
        while cur:
            n += 1
            cur = cur.next
        
        p0 = dummy = ListNode(next=head)
        pre, cur = None, head
        while n >= k:
            n -= k
            for _ in range(k):
                nxt = cur.next
                cur.next = pre
                pre = cur
                cur = nxt
            
            nxt = p0.next
            nxt.next = cur
            p0.next = pre
            p0 = nxt
        
        return dummy.next
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        int n = 0;
        for (ListNode *cur = head; cur; cur = cur->next) n += 1;
        ListNode *dummy = new ListNode(0, head), *p0 = dummy;
        ListNode *pre = nullptr, *cur = head;
        for (; n >= k; n -= k) {
            for (int i = 0; i < k; i ++ ) {
                ListNode *nxt = cur->next;
                cur->next = pre;
                pre = cur, cur = nxt;
            }

            ListNode *nxt = p0->next;
            p0->next->next = cur;
            p0->next = pre;
            p0 = nxt;
        }
        return dummy->next;
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

4、两两交换链表中的节点

Leetcode 24

解法一:迭代

class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        node0 = dummy = ListNode(next=head)
        node1 = head
        while node1 and node1.next:
            node2 = node1.next
            node3 = node2.next
            
            node0.next = node2
            node2.next = node1
            node1.next = node3

            node0 = node1
            node1 = node3
        
        return dummy.next
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        auto dummy = new ListNode(0, head);
        auto node0 = dummy, node1 = head;
        while (node1 && node1->next) {
            auto node2 = node1->next, node3 = node2->next;

            node0->next = node2, node2->next = node1, node1->next = node3;

            node0 = node1, node1 = node3;
        }
        return dummy->next;
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

解法二:递归

class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if head is None or head.next is None:
            return head

        node1 = head
        node2 = head.next
        node3 = node2.next

        node1.next = self.swapPairs(node3)
        node2.next = node1
    
        return node2
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return head;
        auto node1 = head, node2 = head->next, node3 = node2->next;
        node1->next = swapPairs(node3);
        node2->next = node1;
        return node2;
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

5、两数相加 II

Leetcode 445

解法一:迭代写法

class Solution:
    def reverseList(self, head: Optional[ListNode])->Optional[ListNode]:
        pre, cur = None, head
        while cur:
            nxt = cur.next
            cur.next = pre
            pre = cur
            cur = nxt
        return pre
    
    def addTwo(self, l1: Optional[ListNode], l2: Optional[ListNode])->Optional[ListNode]:
        cur = dummy = ListNode()
        carry = 0  # 存储进位
        while l1 or l2 or carry:
            if l1: carry += l1.val
            if l2: carry += l2.val
            cur.next = ListNode(carry % 10)
            carry //= 10
            cur = cur.next
            if l1: l1 = l1.next
            if l2: l2 = l2.next
        return dummy.next

    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        l1 = self.reverseList(l1)
        l2 = self.reverseList(l2)
        l3 = self.addTwo(l1, l2)
        return self.reverseList(l3)
class Solution {
public:
    ListNode *reverseList(ListNode *head) {
        ListNode *pre = nullptr, *cur = head;
        while (cur) {
            ListNode *nxt = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nxt;
        }
        return pre;
    }

    ListNode *addTwo(ListNode *l1, ListNode *l2) {
        auto dummy = new ListNode();
        auto cur = dummy;
        int carry = 0;
        while (l1 || l2 || carry) {
            if (l1) carry += l1->val;
            if (l2) carry += l2->val;
            cur = cur->next = new ListNode(carry % 10);
            carry /= 10;
            if (l1) l1 = l1->next;
            if (l2) l2 = l2->next;
        }
        return dummy->next;
    }

    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        l1 = reverseList(l1);
        l2 = reverseList(l2);
        auto l3 = addTwo(l1, l2);
        return reverseList(l3);
    }
};

解法二:递归写法

class Solution:
    def reverseList(self, head:Optional[ListNode])->Optional[ListNode]:
        if head is None or head.next is None:
            return head
        new_head = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return new_head

    def addTwo(self, l1: Optional[ListNode], l2: Optional[ListNode], carry=0)->Optional[ListNode]:
        if l1 is None and l2 is None:
            return ListNode(carry) if carry else None
        if l1 is None:
            l1, l2 = l2, l1
        carry += l1.val + (l2.val if l2 else 0)
        l1.val = carry % 10
        l1.next = self.addTwo(l1.next, l2.next if l2 else None, carry // 10)
        return l1

    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        l1 = self.reverseList(l1)
        l2 = self.reverseList(l2)
        l3 = self.addTwo(l1, l2)
        return self.reverseList(l3)
class Solution {
public:
    ListNode *reverseList(ListNode *head) {
        if (head == nullptr || head->next == nullptr) return head;
        auto new_head = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return new_head;
    }

    ListNode *addTwo(ListNode *l1, ListNode *l2, int carry = 0) {
        if (l1 == nullptr && l2 == nullptr) 
            return carry ? new ListNode(carry) : nullptr;
        if (l1 == nullptr) swap(l1, l2);
        carry += l1->val + (l2 ? l2->val : 0);
        l1->val = carry % 10;
        l1->next = addTwo(l1->next, (l2 ? l2->next : nullptr), carry / 10);
        return l1;
    }

    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        l1 = reverseList(l1), l2 = reverseList(l2);
        auto l3 = addTwo(l1, l2);
        return reverseList(l3);
    }
};

6、翻倍以链表形式表示的数字

Leetcode 2816

class Solution:
    def doubleIt(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if head.val > 4:
            head = ListNode(0, head)
        cur = head
        while cur:
            cur.val = cur.val * 2 % 10
            if cur.next and cur.next.val > 4:
                cur.val += 1
            cur = cur.next
        return head
class Solution {
public:
    ListNode* doubleIt(ListNode* head) {
        if (head->val > 4) head = new ListNode(0, head);
        for (auto cur = head; cur; cur = cur->next) {
            cur->val = cur->val * 2 % 10;
            if (cur->next && cur->next->val > 4) cur->val += 1;
        }
        return head;
    }
};

你可能感兴趣的:(算法笔记,2,算法,链表,数据结构)