leetcode练习题第一次训练

1.0707. 设计链表

1.1 题目大意

要求:设计实现一个链表,需要支持以下操作:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回 -1
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index, val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果 index 小于 0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

说明

  • 所有val值都在 [1,1000] 之内。
  • 操作次数将在 [1,1000] 之内。
  • 请不要使用内置的 LinkedList 库。

示例

​
MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2);   // 链表变为 1 -> 2 -> 3
linkedList.get(1);            // 返回 2
linkedList.deleteAtIndex(1);  // 现在链表是 1-> 3
linkedList.get(1);            // 返回 3

​

运行 :

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

class MyLinkedList:

    def __init__(self):
        self.head = None

    def get(self, index):
        if not self.head:
            return -1
        cur = self.head
        for i in range(index):
            if cur.next:
                cur = cur.next
            else:
                return -1
        return cur.val if cur else -1

    def addAtHead(self, val):
        new_node = ListNode(val)
        new_node.next = self.head
        self.head = new_node

    def addAtTail(self, val):
        new_node = ListNode(val)
        if not self.head:
            self.head = new_node
            return
        curr = self.head
        while cur.next:
            cur = cur.next
        cur.next = new_node

    def addAtIndex(self, index, val):
        if index == 0:
            self.addAtHead(val)
            return
        cur = self.head
        for i in range(index - 1):
            if cur:
                cur = cur.next
            else:
                return
        if not cur:
            return
        new_node = ListNode(val)
        new_node.next = cur.next
        cur.next = new_node

    def deleteAtIndex(self, index):
        if index == 0:
            if self.head:
                self.head = self.head.next
            return
        cur = self.head
        for i in range(index - 1):
            if cur:
                cur = cur.next
            else:
                return
        if not cur or not cur.next:
            return
        cur.next = cur.next.next

2.0206. 反转链表

2.1 题目大意

描述:给定一个单链表的头节点 head

要求:将该单链表进行反转。可以迭代或递归地反转链表。

说明

  • 链表中节点的数目范围是 [0,5000]。
  • −5000≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤5000。

示例

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

解释
翻转前    1->2->3->4->5->NULL
反转后    5->4->3->2->1->NULL

 运行 :

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution(object):
    def reverseList(self, head):
        cur, pre = head, None
        while cur:
            tmp = cur.next # 暂存后继节点 cur.next
            cur.next = pre # 修改 next 引用指向
            pre = cur      # pre 暂存 cur
            cur = tmp      # cur 访问下一节点
        return pre
        

3.0203. 移除链表元素

3.1 题目大意

描述:给定一个链表的头节点 head 和一个值 val

要求:删除链表中值为 val 的节点,并返回新的链表头节点。

说明

  • 列表中的节点数目在范围 [0,104] 内。
  • 1≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤50。
  • 0≤𝑣𝑎𝑙≤50。

示例

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]


输入:head = [], val = 1
输出:[]

 运行 : 

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution(object):
    def removeElements(self, head, val):
        dummy = ListNode(0) #虚拟的头节点,以便简化删除操作
        dummy.next = head #虚拟头节点指向真正的头节点
        cur_Node = dummy #将cur_Node赋值为虚拟头节点
        while cur_Node.next: #将cur_Node的下一节点作为判断依据
            if cur_Node.next.val == val:
                cur_Node.next = cur_Node.next.next
            else:
                cur_Node = cur_Node.next
        return dummy.next #注意,这里返回的是真实的头节点

 

1.0328. 奇偶链表

1.1 题目大意

描述:给定一个单链表的头节点 head

要求:将链表中的奇数位置上的节点排在前面,偶数位置上的节点排在后面,返回新的链表节点。

说明

  • 要求空间复杂度为 𝑂(1)。
  • 𝑛 等于链表中的节点数。
  • 0≤𝑛≤104。
  • −106≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤106。

示例

输入: head = [1,2,3,4,5]
输出: [1,3,5,2,4]

 

输入: head = [2,1,3,5,6,4,7]
输出: [2,3,6,7,1,5,4]

运行: 

# Definition for singly-linked list.
class ListNode:
     def __init__(self, val=0, next=None):
         self.val = val
         self.next = next
class Solution:
    def oddEvenList(self, head):
        odd = p1 = ListNode()   #奇索引表【头节点】            
        even = p2 = ListNode()  #偶索引表【头节点】
        
        p1.next = p2.next = None    #先让头节点都指向None
        cur = head              #head指向的就是第一个数据节点
        count=1                 #表示索引号,控制奇偶节点剥离
 
        while cur:
            temp=cur.next       #temp是临时保存cur下一个节点的,否则会丢失后续节点
            if count % 2 == 0:  #分析索引的奇偶性,整个if语句实现节点剥离和插入到新表
                cur.next = p1.next
                p1.next = cur
                p1 = cur
            else:
                cur.next = p2.next
                p2.next = cur
                p2 = cur
 
            cur = temp          #cur移动到后续未剥离的节点序列的第一个节点
            count+=1            #每处理完一个,cur已经移动到下一个节点了,则索引+1
 
        p2.next = odd.next      #将【奇索引表】的尾巴和【偶索引表】的第一个节点连接
        return even.next        #返回重新排列后的链表的第一个数据节点

2.0234. 回文链表

2.1 题目大意

描述:给定一个链表的头节点 head

要求:判断该链表是否为回文链表。

说明

  • 链表中节点数目在范围 [1,105] 内。
  • 0≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤9。

示例

输入:head = [1,2,2,1]
输出:True

 

输入:head = [1,2]
输出:False

运行:

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

        # 先把链表内容复制进入数组中
        nums = [] # 创建一个空数组/列表,用来先讲链表复制到数组中
        cur = head # 创建 cur 指向 head
        while cur is not None: # 如果指针不为空
            nums.append(cur.val) # 将当前指针所指的 value 复制添加进入数组
            cur = cur.next # 更新 cur 指针

        # 直接比较原数组/列表和反转数组/列表
        return nums == nums[::-1]

 

3.0138. 复制带随机指针的链表

3.1 题目大意

描述:给定一个链表的头节点 head,链表中每个节点除了 next 指针之外,还包含一个随机指针 random,该指针可以指向链表中的任何节点或者空节点。

要求:将该链表进行深拷贝。返回复制链表的头节点。

说明

  • 0≤𝑛≤1000。
  • −104≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤104。
  • Node.random 为 null 或指向链表中的节点。

示例

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

 

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

运行:

 


# Definition for a Node.
# class Node:
#     def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
#         self.val = int(x)
#         self.next = next
#         self.random = random

 
class Solution(object):
    def copyRandomList(self, head):
        if not head:
            return None
        node_map={}
        cur=head
        while cur:
            node_map[cur]=Node(cur.val)
            cur=cur.next
        cur=head
        while cur:
            if cur.next:
                node_map[cur].next=node_map[cur.next]
            if cur.random:
                node_map[cur].random=node_map[cur.random]
            cur=cur.next
        return node_map[head]

1.0147. 对链表进行插入排序

1.1 题目大意

描述:给定链表的头节点 head

要求:对链表进行插入排序。

说明

  • 插入排序算法:
    • 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
    • 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
    • 重复直到所有输入数据插入完为止。
  • 列表中的节点数在 [1,5000] 范围内。
  • −5000≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤5000。

示例

输入: head = [4,2,1,3]
输出: [1,2,3,4]

 

输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]

运行:

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
 
class Solution:
    def insertionSortList(self, head):
        if head == None or head.next == None:
            return head
        dummy = ListNode(0)
        dummy.next = head
        last_sorted = head  # 已排序部分的最后一个节点
        cur = head.next  # 待插入的
 
        while cur:
            if last_sorted.val <= cur.val:
                last_sorted = last_sorted.next
            else:
                # 从链表的头节点开始往后遍历链表中的节点,寻找插入 cur 的位置
                prev = dummy
                while prev.next.val <= cur.val:
                    prev = prev.next
                # 插入操作:令 prev 为插入 cur 的位置的前一个节点
                last_sorted.next = cur.next
                cur.next = prev.next
                prev.next = cur
            cur = last_sorted.next
        return dummy.next

2.0021. 合并两个有序链表

2.1 题目大意

描述:给定两个升序链表的头节点 list1 和 list2

要求:将其合并为一个升序链表。

说明

  • 两个链表的节点数目范围是 [0,50]。
  • −100≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤100。
  • list1 和 list2 均按 非递减顺序 排列

示例

输入:list1 = [1,2,4], list2 = [1,3,4]
输出:[1,1,2,3,4,4]


输入:list1 = [], list2 = []
输出:[]

运行:

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

class Solution:
    def mergeTwoLists(self,l1,l2):
        # 创建一个哑节点作为合并链表的头部
        head=ListNode(0)
        # 创建一个指针用于遍历合并链表
        cur=head
        # 当两个链表同时都有节点时
        while l1 and l2:
            # 如果链表l1节点的值>=l2节点的值,将l2当前节点赋予current的下一个节点
            # 将l2指向其下一个节点
            if l1.val>=l2.val:
                cur.next=l2
                l2=l2.next
            else:
                cur.next=l1
                l1=l1.next
            cur=cur.next
        # 将剩余部分连接到合并链表的末尾
        cur.next= l1 if l1 else l2
        return head.next

3.0148. 排序链表

3.1 题目大意

描述:给定链表的头节点 head

要求:按照升序排列并返回排序后的链表。

说明

  • 链表中节点的数目在范围 [0,5∗104] 内。
  • −105≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤105。

示例

输入:head = [4,2,1,3]
输出:[1,2,3,4]

 

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

运行:

class Solution:
    def bubbleSort(self, head):
        node_i = head
        tail = None
        # 外层循环次数为 链表节点个数
        while node_i:
            node_j = head
            while node_j and node_j.next != tail:
                if node_j.val > node_j.next.val:
                    # 交换两个节点的值
                    node_j.val, node_j.next.val = node_j.next.val, node_j.val
                node_j = node_j.next
            # 尾指针向前移动 1 位,此时尾指针右侧为排好序的链表
            tail = node_j
            node_i = node_i.next
            
        return head

    def sortList(self, head):
        return self.bubbleSort(head)

 

1.0141. 环形链表

1.1 题目大意

描述:给定一个链表的头节点 head

要求:判断链表中是否有环。如果有环则返回 True,否则返回 False

说明

  • 链表中节点的数目范围是 [0,10^4]。
  • −105≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤105。
  • pos 为 -1 或者链表中的一个有效索引。

示例

输入:head = [3,2,0,-4], pos = 1
输出:True
解释:链表中有一个环,其尾部连接到第二个节点。

输入:head = [1,2], pos = 0
输出:True
解释:链表中有一个环,其尾部连接到第一个节点。

运行:

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

# 快慢双指针
class Solution(object):
    def hasCycle(self, head):
        if not head:
            return None
        slow, quick = head, head.next             # 快慢指针
        while slow!=quick:              
            if quick==None or quick.next==None:   # 快指针或快指针的next为空,则遍历至链表尾部,非环形链表
                return False
            else:
                slow = slow.next                 # 慢指针走一步
                quick = quick.next.next          # 快指针走两步
        return True                              # 快慢指针相遇,则为环形链表

 

2.0142. 环形链表 II

2.1 题目大意

描述:给定一个链表的头节点 head

要求:判断链表中是否有环,如果有环则返回入环的第一个节点,无环则返回 None

说明

  • 链表中节点的数目范围在范围 [0,104] 内。
  • −105≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤105。
  • pos 的值为 -1 或者链表中的一个有效索引。

示例

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

运行: 

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

class Solution:
    def hasCycle(self, head):
        fast = head
        slow = head
        #根据快指针能不能指到空来判断这是单向链表还是带有环的链表
        while fast and fast.next:
            fast = fast.next.next #快指针一次走两格
            slow = slow.next #慢指针一次走一格
            if fast == slow: #如果两个指针能够相遇,就说明是有环的
                #确定有环之后,就要在相遇的节点新设一个节点index1
                #在头节点新设一个节点index2
                #两者同步走,相遇处即为入环口
                index1 = fast
                index2 = head
                #遍历结束条件为两者相遇
                while index1 != index2:
                    index1 = index1.next
                    index2 = index2.next
                #相遇之后返回节点
                return index1 
        return None

3.0019. 删除链表的倒数第 N 个结点

3.1 题目大意

描述:给定一个链表的头节点 head

要求:删除链表的倒数第 n 个节点,并且返回链表的头节点。

说明

  • 要求使用一次遍历实现。
  • 链表中结点的数目为 sz
  • 1≤𝑠𝑧≤30。
  • 0≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤100。
  • 1≤𝑛≤𝑠𝑧。

示例

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]


输入:head = [1], n = 1
输出:[]

运行: 

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def removeNthFromEnd(self, head, n):
        dummy = ListNode(0)  # 创建一个虚拟头结点,值为0
        dummy.next = head  # 将虚拟头结点指向原链表的头结点
        fast = dummy  # 快指针初始指向虚拟头结点
        slow = dummy  # 慢指针初始指向虚拟头结点
        
        for i in range(n+1):  # 快指针先向前移动n步(包括虚拟头结点)
            fast = fast.next
        
        while fast:  # 同时移动快指针和慢指针,直到快指针到达链表末尾
            fast = fast.next  # 快指针每次移动一步
            slow = slow.next  # 慢指针每次移动一步
        
        slow.next = slow.next.next  # 删除倒数第n个节点,将慢指针指向的节点的next指针指向下一个节点的next指针
        
        return dummy.next  # 返回链表的头结点


        

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值