链表

作者: yy辰 | 来源:发表于2018-10-15 13:41 被阅读18次

今天开始抽空刷一些leetcode里数据结构的题,在这里记录下来。按难易程度开始刷吧。

第一次更新:2018.10.15

237、删除链表中的节点
开始看题的时候有点懵,没太懂题目意思,删除链表中值为某个值的节点,但题目没有给定链表。后来想了一会,直接用该链表的下一个节点覆盖掉这个节点就可以了。

class Solution(object):
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        if node:        
            node.val = node.next.val
            node.next = node.next.next

206、反转链表
先用迭代实现

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        a, b, c = None, head, head.next
        while c:
            b.next = a
            a, b, c = b, c, c.next
        b.next = a
        return b

再用递归

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        elif not head.next:
            return head
        new_head = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return new_head

21、合并两个有序链表

class Solution(object):
    def mergeTwoLists(self, l1, l2):
        head = ListNode(-1)
        temp = head
        while l1 and l2:
            if l1.val <= l2.val:
                temp.next = l1
                l1 = l1.next
                temp = temp.next
            else:
                temp.next = l2
                l2 = l2.next
                temp = temp.next
        if l1:
            temp.next = l1
        if l2:
            temp.next = l2
        return head.next

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

class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        else:
            temp = head
            cur = head.next
            while cur:
                if cur.val != temp.val:
                    temp.next = cur
                    temp = temp.next
                cur = cur.next
            temp.next = None
            return head

203、移除链表元素

class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """ 
        new_head = ListNode(val-1)
        temp = new_head
        cur = head
        while cur:
            if cur.val != val:
                temp.next = cur
                temp = temp.next
            cur = cur.next
        temp.next = None
        return new_head.next

234、回文链表
第一次做的时候把值存在了列表里,然后判断列表是不是回文列表。可以用双指针找到中间的节点,还要用到之前的反转链表,代码比较长,也是调试了几次才AC。


class Solution(object):
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        def reverseList(head):
            """
            :type head: ListNode
            :rtype: ListNode
            """
            if not head:
                return None
            a, b, c = None, head, head.next
            while c:
                b.next = a
                a, b, c = b, c, c.next
            b.next = a
            return b

        if not head or not head.next:
            return True
        slow = head
        fast = head
        while fast.next:
            if not fast.next.next:
                break
            else:
                fast = fast.next.next
                slow = slow.next
        new_listnode = reverseList(slow.next)
        p = new_listnode
        q = head
        while p:
            if p.val != q.val:
                return False
            p = p.next
            q = q.next
        return True
        

第二次更新:2018.10.16

141、环形链表
使用快指针和慢指针就可以了

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if not head:
            return False
        slow = head
        fast = head
        while fast:
            if fast.next:
                fast = fast.next.next
                slow = slow.next
                if fast == slow:
                    return True
            else:
                return False
        else:
            return False

160、相交链表
剑指offer里面也有这题

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        p1 = headA
        p2 = headB
        while p1 != p2:
            p1 = p1.next if p1.next else headB
            p2 = p2.next if p2.next else headA
        return p1

109、有序链表转换二叉搜索树
今天在剑指offer里刷了一道二叉搜索树转双向链表的,这道题反过来将链表转二叉搜索树。有序链表的顺序就是二叉搜索树的中序遍历的顺序。
只要找到中间的节点,然后递归就可以了。但是链表找中间节点有点麻烦,可以用笨办法先转为列表再找中间节点,然后重新转化为节点。但用双指针也可以找到中间节点,不过在递归过程中不断找中间节点有点困难,没有写出来。还是参考了别人的代码

class Solution(object):
    def sortedListToBST(self, head):
        """
        :type head: ListNode
        :rtype: TreeNode
        """

        def convert(head, tail):
            if head == tail:
                return None
            if head.next == tail:
                return TreeNode(head.val)
            fast = head
            mid = head
            while fast != tail and fast.next != tail:
                fast = fast.next.next
                mid = mid.next
            root = TreeNode(mid.val)
            root.left = convert(head, mid)
            root.right = convert(mid.next, tail)
            return root

        return convert(head, None)

24、两两交换链表中的节点
直接用递归

class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        if not head.next:
            return head
        a, b = head, head.next
        temp = self.swapPairs(b.next)
        b.next = a
        a.next = temp
        return b

114、二叉树转为链表
要求原地修改二叉树,所以不能先序遍历再连接。

class Solution(object):
    def flatten(self, root):
        if not root:
            return None
        if root.left:
            self.flatten(root.left)
        if root.right:
            self.flatten(root.right)
        temp = root.right
        root.right = root.left
        root.left = None
        while root.right:
            root = root.right
        root.right = temp

148、排序链表
题目要求了时间复杂度:O(n log n)。好像快排,归并排序,堆排序都是O(n log n)级别的,但我还没看,先跳过


382、链表随机节点
获得长度后用random模块随机一个数字代表第几个节点

class Solution(object):

    def __init__(self, head):
        """
        @param head The linked list's head.
        Note that the head is guaranteed to be not null, so it contains at least one node.
        :type head: ListNode
        """
        import random
        self.head = head

    def getRandom(self):
        """
        Returns a random node's value.
        :rtype: int
        """
        if not self.head:
            return None
        length = 0
        cur = self.head
        while cur:
            length += 1
            cur = cur.next
        index = random.randint(0, length-1)
        cur = self.head
        for i in range(length):
            if i == index:
                return cur.val
            else:
                cur = cur.next
                i += 1

147、对链表进行插入排序
剑指offer刷完我就去看排序!先跳过

328、奇偶链表
用了三个指针。

class Solution(object):
    def oddEvenList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head or not head.next:
            return head
        a, b, c = head, head.next, head.next.next
        new_head = b
        i = 0
        while c:
            i += 1 
            a.next = c
            a, b, c = b, c, c.next
        if i%2 == 0:
            a.next = new_head
        else:
            b.next = new_head
            a.next = None
        return head

第三次更新:2018.10.17
明天要开组会,准备了一晚上组会的东西= =,抓紧时间写两道题

143、重排链表
写了很久,想法是后半段链表先翻转,然后前半段和后半段交叉连接就可以了。

class Solution(object):
    def reorderList(self, head):

        def reverse(head):
            if not head:
                return None
            a, b, c = None, head, head.next
            while c:
                b.next = a
                a, b, c = b, c, c.next
            b.next = a
            return b

        if  head and head.next:
            fast = head
            slow = head
            while fast.next:
                if fast.next.next:
                    fast = fast.next.next
                    slow = slow.next
                else:
                    break
            new_head = reverse(slow.next)
            a = head
            b = new_head
            final_head = ListNode(0)
            temp = final_head
            i = 0
            while b:
                if i%2==0:
                    temp.next = a
                    temp = temp.next
                    a = a.next
                if i%2 == 1:
                    temp.next = b
                    temp = temp.next
                    b = b.next
                i += 1
            temp.next = a
            if temp.next:
                temp.next.next = None
            head = temp.next

2、两数相加
最简单的可以直接将数值取出来再相加。当然有更好的解法,参考了别人的,用memory记录进位

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        mem = 0
        new_head = ListNode(0)
        cur = new_head
        while l1 or l2:
            a = l1.val if l1 else 0
            b = l2.val if l2 else 0
            c = a + b
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next
            cur.next = ListNode((c+mem)%10)
            cur = cur.next
            mem = (c+mem) // 10
        if mem != 0:
            cur.next = ListNode(mem)
        return new_head.next

445、两数相加Ⅱ
这题跟上一题类似,不过上一题最高位处于链表的尾节点,这题最高位处于头节点。简单一点的可以将两个链表反转后再复制上一题的代码,但应该有更好的答案,但我没想出来。网上搜了一下其实就是把值都取出来存在栈里==。看来是我想复杂了

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        stack1 = []
        stack2 = []
        while l1:
            stack1.append(l1.val)
            l1 = l1.next
        while l2:
            stack2.append(l2.val)
            l2 = l2.next
        answer = None
        carry = 0
        while stack1 and stack2:
            add = stack1.pop() + stack2.pop() + carry
            carry = 1 if add >= 10 else 0
            temp = answer
            answer = ListNode(add % 10)
            answer.next = temp
        l = stack1 if stack1 else stack2
        while l:
            add = l.pop() + carry
            carry = 1 if add >= 10 else 0
            temp = answer
            answer = ListNode(add % 10)
            answer.next = temp
        if carry:
            temp = answer
            answer = ListNode(1)
            answer.next = temp
        return answer

86、分隔链表
用了个比较笨的办法,用一个新链表存储小于目标值的节点,另一个新链表存储其它节点,最后再合并

class Solution(object):
    def partition(self, head, x):
        """
        :type head: ListNode
        :type x: int
        :rtype: ListNode
        """
        smallhead = ListNode(-1)
        bighead = ListNode(-1)
        a , b= smallhead, bighead
        cur = head
        while cur:
            if cur.val < x:
                a.next = cur
                a = a.next
                cur = cur.next
            else :
                b.next = cur
                b = b.next
                cur = cur.next
        a.next = None
        b.next = None
        cur = smallhead
        while cur.next:
            cur = cur.next
        cur.next = bighead.next
        return smallhead.next

92、反转链表Ⅱ
跟反转链表第一题差不多,注意一下反转的界限就可以了。实际写的时候出了很多问题,最终还是没写出来。。参考别人代码,实际思路是一样的

class Solution:
    def reverseBetween(self, head, m, n):
        """
        :type head: ListNode
        :type m: int
        :type n: int
        :rtype: ListNode
        """
        if head == None or head.next == None or m >= n or m < 0 or n < 0:
            return head

        h = ListNode(-1)
        h.next = head
        pre = h
        cur = head
        i = 1
        while i < m and cur != None:
            pre = cur
            cur = cur.next
            i += 1

        t1 = pre
        t2 = cur

        while i <= n and cur != None:
            lat = cur.next
            cur.next = pre
            pre = cur 
            cur = lat
            i += 1

        t1.next = pre
        t2.next = cur
        return h.next

2018.10.20

82、删除链表中的重复元素Ⅱ

class Solution:
    # @param head, a ListNode
    # @return a ListNode
    def deleteDuplicates(self, head):
        if not head:
            return None
        new_head = ListNode(head.val - 1)
        temp = new_head
        a, b, c = temp, head, head.next
        while b:
            if not c:
                if b.val != a.val:
                    temp.next = b
                    break
                else:
                    temp.next = None
                    break
            elif a.val != b.val != c.val:
                temp.next = b
                temp = b
                a, b, c = b, c, c.next
            else:
                a, b, c = b, c, c.next
        b.next = None
        return new_head.next

61、旋转链表
调试了很久才AC。

class Solution(object):
    def rotateRight(self, head, k):
        if not head:
            return None
        if k == 0:
            return head
        length = 0
        cur = head
        while cur:
            length += 1
            cur = cur.next
        if length == 1 or k%length==0:
            return head
        pos = length - k % length + 1
        cur = head
        i = 1
        while i < pos-1:
            cur = cur.next
            i += 1
        temp = cur
        new_head = cur.next
        cur = cur.next
        while cur.next:
            cur = cur.next
        temp.next = None
        cur.next = head
        return new_head

19、删除链表的倒数第N个节点
遍历两遍链表的话很容易,但一遍的话没想到该怎么做。参考别人的答案:https://blog.csdn.net/dongrongyu/article/details/78346583

想法是这样的:维护两个指针,pre和end。一开始初始化时使得pre指针指向链表头节点,end指针指向pre+n的节点位置。然后同时往后移动pre和end指针位置,使得end指针指向最后一个节点,那么pre指针指向的则是end-n的节点位置(即倒数第n个元素的前一个节点),则将其删除。

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        if not head:
            return None
        fast = head
        for i in range(n):
            fast = fast.next
        if not fast:
            return head.next
        slow = head
        while fast.next:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return head

142、环形链表Ⅱ
剑指offer里刷过了

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        fast = head
        slow = head
        while fast.next:
            if not fast.next.next:
                return None
            else:
                fast = fast.next.next
                slow = slow.next
                if fast == slow:
                    if fast==head:
                        return head
                    slow = head
                    while True:
                        fast = fast.next
                        slow = slow.next
                        if fast == slow:
                            return fast
        return None

相关文章

  • 链表基础

    链表基础 链表长度 链表为空 链表结构 链表增加

  • 双向链表&双向循环链表

    链表分为:单链表、单向循环链表、双向链表、双向循环链表本节主要说明:双向链表、双向循环链表 定义结点 一、双向链表...

  • 算法与数据结构:链表

    链表 链表还分为单向链表和双向链表, 但是这篇文章只说单向链表 , 下次再讲双向链表 . 链表和数组的区别 ? 链...

  • 链表

    链表 单链表反转链表中环的检测两个有序链表合并删除链表倒数第n个节点求链表的元素总个数 一.单向链表 链表共有特征...

  • 五、双向链表

    双向链表 此前介绍的链表,也叫做单向链表使用双向链表可以提升链表的综合性能 修改之前的单链表的源码: 双向链表 –...

  • 链表

    内容 链表数据结构 向链表添加元素 从链表移除元素 使用 LinkedList 表 双向链表 循环链表 链表数据结...

  • 数据与算法结构

    线性表 顺序表 链表(物理上离散,逻辑上连续) 链表的类别 单链表 循环链表 双链表 链表的操作 顺序表与链表的比...

  • 数据结构——链表

    本文所讲的链表是单链表,链表采用无头链表 科普下:一般链表可以分为有头节点的链表与无头节点的链表 有头节点的链表:...

  • 链表

    文章结构 链表的定义 链表的插入和删除操作 链表的特性 常见的链表结构 自定义链表 链表的经典操作 使用链表实现L...

  • Algorithm小白入门 -- 单链表

    单链表递归反转链表k个一组反转链表回文链表 1. 递归反转链表 单链表节点的结构如下: 1.1 递归反转整个单链表...

网友评论

    本文标题:链表

    本文链接:https://www.haomeiwen.com/subject/aqtfzftx.html