[leetcode] 数组、链表练习题

本文深入解析了数组与链表的经典算法题目,包括盛水容器、爬楼梯、三数之和等,提供了多种解题思路,如双指针、递归、快慢指针等,并附有详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数组与链表

Array 实战题目

1. 盛最多水的容器

在这里插入图片描述

class Solution:
    def maxArea(self, height: List[int]) -> int:
        # 1. 双指针法, 用max_area保存最大值
        left_point = 0
        right_point = len(height) - 1
        max_area = 0
        while left_point < right_point:
            area = min(height[right_point], height[left_point]) * (right_point - left_point)
            max_area = max(area, max_area)
            if height[left_point] < height[right_point]:
                left_point += 1
            else:
                right_point -= 1
        return max_area

2. 爬楼梯

func climbStairs(n int) int {
    // 1. 斐波那契 递归
	if n < 3 {
		return n
	}
	return climbStairs(n-1) + climbStairs(n-2)
}
class Solution:
    def climbStairs(self, n: int) -> int:
        # 1. 斐波那契数列,递推
        if n <= 0:
            return 0
        res, last = 1, 1
        for _ in range(1, n):
            res, last = res + last, res
        return res
        # 2. 斐波那契公式
        sqrt_5 = math.sqrt(5)
        fib_n = math.pow((1+sqrt_5)/2, n+1) - math.pow((1-sqrt_5)/2, n+1)
        return int(fib_n/sqrt_5)

3. 三数之和

三数之和

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        res = []
        for i in range(len(nums)):
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            l, r = i + 1, len(nums) - 1
            while l < r:
                ans = nums[i] + nums[l] + nums[r]
                if ans < 0:
                    l += 1
                elif ans > 0:
                    r -= 1
                else:
                    res.append([nums[i], nums[l], nums[r]])
                    # break
                    while l < r and nums[l] == nums[l + 1]:
                        l += 1
                    while l < r and nums[r] == nums[r - 1]:
                        r -= 1
                    l += 1
                    r -= 1
        return res

Linked List 实战题目

1. 反转链表

反转链表

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        # 1. 指针法
        # 申请两个节点,pre和 cur,pre指向None
        pre = None
        cur = head
        while cur:
            # 记录当前节点的下一个节点
            tmp = cur.next
            # 然后将当前节点指向pre
            cur.next = pre
            # pre和cur节点都前进一位
            pre, cur = cur, tmp
        return pre

        # 2. 递归解法
        # 2.1 终止条件是当前节点或者下一个节点 == null
        # 2.2 在函数内部,改变节点的指向,也就是head的下一个节点指向head递归函数那句
        # 递归终止条件是当前为空,或者下一个节点为空
        if head is None or head.next is None:
            return head
        # 这里的cur就是最后一个节点
        cur = self.reverseList(head.next)
        head.next.next = head
        # 防止链表循环,需要将head.next设置为空
        head.next = None
        # 每层递归函数都返回cur,也就是最后一个节点
        return cur

2. 两两交换链表中的节点

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

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        # 递归方法
        # 结束条件:
        if not head or not head.next:
            return head
        
        pre_point = head
        after_point = head.next
        # 交换两节点
        pre_point.next = self.swapPairs(after_point.next)
        after_point.next = pre_point
        
        return after_point

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        # 方法二:
        thead = ListNode(-1)
        thead.next = head
        c = thead
        while c.next and c.next.next:
            a, b = c.next, c.next.next
            c.next, a.next = b, b.next
            b.next = a
            c = c.next.next
        return thead.next

3. 环形链表

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        # 方法1: 哈希表
        # 从头遍历链表,将遍历到的元素放入字典里,如果有环的情况下那么必然会重复出现在哈希表;如果没有环,那么指针移动到最后就退出
        dic = {}
        while head:
            if head in dic:
                return True
            else:
                dic[head] = 1
            head = head.next
        return False

        # 方法2: 快慢指针追该碰撞
        if not head:
            return False
        slow = head
        quick = head
        while quick and slow:
            slow = slow.next
            if quick.next:  # quick跳两次,所以要判断quick.next是否为空
                quick = quick.next.next
            else:
                return False
            if quick is slow:
                return True
        return False

4. 环形链表 II

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        # 方法1: 哈希表
        visited = set()
        node = head
        while node:
            if node in visited:
                return node
            else:
                visited.add(node)
                node = node.next
        return None

        # 方法2: Floyd算法(双指针两次相遇)
        fast, slow = head, head
        while True:
            if not (fast and fast.next):
                return
            fast, slow = fast.next.next, slow.next
            if fast == slow:
                break
        fast = head
        while fast != slow:
            fast, slow = fast.next, slow.next
        return fast

5. K 个一组翻转链表

在这里插入图片描述

class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        dummy = ListNode(0)
        p = dummy
        while True:
            count = k 
            stack = []
            tmp = head
            while count and tmp:
                stack.append(tmp)
                tmp = tmp.next
                count -= 1
            # 注意,目前tmp所在k+1位置
            # 说明剩下的链表不够k个,跳出循环
            if count : 
                p.next = head
                break
            # 翻转操作
            while stack:
                p.next = stack.pop()
                p = p.next
            #与剩下链表连接起来 
            p.next = tmp
            head = tmp
        
        return dummy.next

练习

1. 删除排序数组中的重复项

在这里插入图片描述

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        # 思路1. 快慢指针,i是慢指针,j为快指针。如果nums[i]=nums[j],增加j以跳过。如果nums[j]!=nums[i],将快指针处的值复制到i+1处,
        #       最后返回的数为i+1
        if len(nums) == 0:
            return 0
        i = 0
        for j in range(1, len(nums)):
            if nums[j] != nums[i]:
                i += 1
                nums[i] = nums[j]
        return i + 1
func removeDuplicates(nums []int) int {
   i := 0
   for j := 1; j < len(nums); j++ {
      if nums[j] != nums[i] {
         i++
         nums[i] = nums[j]
      }
   }
   return i + 1
}

2. 旋转数组

image.png
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # 1. python 数组切片
        nums[:] = nums[len(nums) - k:] + nums[:len(nums) - k]

        # 2. 模拟插入
        while k != 0:
            nums.insert(0, nums.pop())
            k -= 1

        # 3. 三次翻转
        n = len(nums)
        k %= n
        nums[:] = nums[::-1]
        nums[:k] = nums[:k][::-1]
        nums[k:] = nums[k:][::-1]

3. 合并两个有序链表

image.png
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        # 方法1: 递归方法
        if l1 is None:
            return l2
        elif l2 is None:
            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

4. 合并两个有序数组

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        nums1[:] = sorted(nums1[:m] + nums2[:n])
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        # 双指针做法
        nums1_copy = nums1[:m]
        nums1[:] = []
        p1, p2 = 0, 0

        while p1 < m and p2 < n:
            if nums1_copy[p1] < nums2[p2]:
                nums1.append(nums1_copy[p1])
                p1 += 1
            else:
                nums1.append(nums2[p2])
                p2 += 1

        if p1 < m:
            nums1[p1 + p2:] = nums1_copy[p1:]
        if p2 < n:
            nums1[p1 + p2:] = nums2[p2:]

5. 两数之和

在这里插入图片描述

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        ans_map = dict()
        for i in range(len(nums)):
            want = target - nums[i]
            if want in ans_map:
                return [ans_map[want], i]
            ans_map[nums[i]] = i

6. 移动零

移动零

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # 解法 1: 快慢指针
        j = 0
        for i in range(len(nums)):
            if nums[i] != 0:
                nums[i], nums[j] = nums[j], nums[i]
                j = j + 1

        # 解法2: python 内置函数
        for i in range(nums.count(0)):
            nums.remove(0)
            nums.append(0)
func moveZeroes(nums []int)  {
	var j = 0
	for i := 0; i < len(nums); i++ {
		if nums[i] != 0 {
		    nums[j] =  nums[i]
            if i != j{
                nums[i] = 0
            }
            j++  // j 始终与0为伴
		}
	}
}

7. 加一

image.png
class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        for i in range(len(digits) - 1, -1, -1):
            if digits[i] != 9:
                digits[i] += 1
                return digits
            digits[i] = 0
        return [1] + digits  # 处理 [9]这种特例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值