一文搞定链表面试题(不定期更新链表提醒及解题思路大杂烩)Middle of the Linked List\合并有序链表\链表反转\删除链表元素

链表题目集锦

  • 返回链表中间数
    • 借助列表实现
    • Java借助链表长度实现
    • Python指针解法
  • 链表反转
    • 借助Python列表反转链表
    • 就地反转链表
  • 合并两个有序链表
    • 列表实现
    • 递归实现
  • 删除链表中的特定元素
    • Python列表实现
    • 递归实现[5]

返回链表中间数

题目:返回列表中间数,如果链表长度为奇数,中间数即为中间位置的数值。如果链表长度为偶数,则返回是链表中间两位偏向于右边的数值[1]。
Leetcode链接
直接上代码吧,后期不定期更新链表相关题目。

借助列表实现

class Solution:
    def middleNode(self, head):
        nodes = []

        while head is not None:
            nodes.append(head)
            head = head.next

            # node = nodes[len(nodes)//2]
        # return node
        return nodes[len(nodes)//2]

一个完整案例代码如下:

#
#
# Definition for singly-linked list.
from pandas import json


class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    def middleNode(self, head):
        nodes = []

        while head is not None:
            nodes.append(head)
            head = head.next

            # node = nodes[len(nodes)//2]
        # return node
        return nodes[len(nodes)//2]

def stringToIntegerList(input):
    return json.loads(input)

def stringToListNode(input):
    # Generate list from the input
    numbers = stringToIntegerList(input)

    # Now convert that list into linked list
    dummyRoot = ListNode(0)
    ptr = dummyRoot
    for number in numbers:
        ptr.next = ListNode(number)
        ptr = ptr.next

    ptr = dummyRoot.next
    return ptr

def listNodeToString(node):
    if not node:
        return "[]"

    result = ""
    while node:
        result += str(node.val) + ", "
        node = node.next
    return "[" + result[:-2] + "]"

def main():
    import sys
    def readlines():
        for line in sys.stdin:
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines)
            head = stringToListNode(line);

            ret = Solution().middleNode(head)

            out = listNodeToString(ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

Java借助链表长度实现

class Solution {
    public ListNode middleNode(ListNode head) {
        if(head == null) return head;

        int len = 0;
        ListNode current = head;
        while(current != null) {
            len++;
            current = current.next;
        }
        
        len /= 2;
        current = head;
        while(len > 0) {
            current = current.next;
            len--;
        }
        
        return current;
    }
}

Python指针解法

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def middleNode(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        tmp = head
        while tmp and tmp.next:
            head = head.next
            tmp = tmp.next.next
        return head

后续有时间更新链表定义、常见题型及解题方法
----------------------我是分割线-------------------------

链表反转

题目:给定一个单链表,求该链表反转后的链表。Leetcode链接
       此题需要先确定是否能够独立开辟空间或者新建链表。分两种情况作答。
       首先,链表在python中有两种表达方式,一是用类建立节点,定义两个指针进行表达,另一个是用列表表达。分别采用两种方式进行解析:

借助Python列表反转链表

       我们可以这么来想:每遍历一次链表,将链表的数值域的数值存储到一个列表中,这样链表遍历完成后即生成一个顺序链表元素的列表,然后再将列表反转输出就可以了。
代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        result=[]
        while head is not None:
            result.append(head.val)
            head = head.next
        result = result[::-1]
        return result

       但是该种解法因为要遍历链表,时间复杂度O(n)。因为要新开辟一个列表,并且要写入与原链表同等长度的元素,故而空间复杂度也为O(n)。

就地反转链表

       之前的解法是O(n)空间,我们可以用O(1)空间完成这件事情。举个例子,方便理解(手写了下):
一文搞定链表面试题(不定期更新链表提醒及解题思路大杂烩)Middle of the Linked List\合并有序链表\链表反转\删除链表元素_第1张图片一文搞定链表面试题(不定期更新链表提醒及解题思路大杂烩)Middle of the Linked List\合并有序链表\链表反转\删除链表元素_第2张图片一文搞定链表面试题(不定期更新链表提醒及解题思路大杂烩)Middle of the Linked List\合并有序链表\链表反转\删除链表元素_第3张图片依据此思路,写代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if head == None or head.next == None:
            return head
        else:
            cur = head
            new_head = None
            tmp = None
            while(cur):
                tmp = cur.next
                cur.next = new_head
                new_head = cur
                cur = tmp
            return new_head

合并两个有序链表

题目[3]:

列表实现

思路:就是将链表数值分别放置在两个链表空间种,然后合并成为一个列表再排序。直接上代码:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        result1 = []
        result2 = []
        result = []
        while l1 is not None:
            result1.append(l1.val)
            l1 = l1.next
        while l2 is not None:
            result2.append(l2.val)
            l2 = l2.next
        result = result1 + result2
        result.sort()
        return result

一个优化的地方可以只借助于O(max(m,n))的空间,直接上代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        result = []
        while l1 is not None:
            result.append(l1.val)
            l1 = l1.next
        while l2 is not None:
            result.append(l2.val)
            l2 = l2.next
        result.sort()
        return result

至于Pythonsort究竟如何实现排序的,我会抽空写一篇博客单独讲讲排序及在Python/Java/Scala种内置函数的源码实现和八大排序实现。

递归实现

删除链表中的特定元素

题目:给定一个链表的头节点head和删除的元素值val,返回删除所有val之后的链表。

Python列表实现

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        cur = head
        result = []
        while(cur):
            if cur.val != val:
                result.append(cur.val)
            cur = cur.next
        return result

时间复杂度、空间复杂度都是O(n)

递归实现[5]

Java实现:

public ListNode removeElements(ListNode head, int val) {
        if (head == null) return null;
        head.next = removeElements(head.next, val);
        return head.val == val ? head.next : head;
}

改写为Python实现:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        if head is None:
            return head
        if (head.val == val):
            return self.removeElements(head.next, val)
        else:
            head.next = self.removeElements(head.next, val)
            return head

def stringToIntegerList(input):
    return json.loads(input)

def stringToListNode(input):
    # Generate list from the input
    numbers = stringToIntegerList(input)

    # Now convert that list into linked list
    dummyRoot = ListNode(0)
    ptr = dummyRoot
    for number in numbers:
        ptr.next = ListNode(number)
        ptr = ptr.next

    ptr = dummyRoot.next
    return ptr

def listNodeToString(node):
    if not node:
        return "[]"

    result = ""
    while node:
        result += str(node.val) + ", "
        node = node.next
    return "[" + result[:-2] + "]"

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines)
            head = stringToListNode(line);
            line = next(lines)
            val = int(line);
            
            ret = Solution().removeElements(head, val)

            out = listNodeToString(ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

Ref:
1、取链表中间数
1.2、参考Leetcode的Java解法
1.3、参考Leetcode的Python解法
2、链表反转
3、合并两个有序链表
4、移除链表中的特定元素
5、递归实现移除链表中特定元素

你可能感兴趣的:(python,Leetcode,面试)