数组和链表
关于数组和链表的几个必知必会的代码实现
数组
实现一个支持动态扩容的数组
实现一个大小固定的有序数组,支持动态增删改操作
实现两个有序数组合并为一个有序数组
链表
实现单链表、循环链表、双向链表,支持增删操作
实现单链表反转
实现两个有序的链表合并为一个有序链表
实现求链表的中间结点
对应的 LeetCode 练习题(@Smallfly 整理)
数组
Three Sum(求三数之和)
英文版:https://leetcode.com/problems/3sum/
中文版:https://leetcode-cn.com/problems/3sum/
Majority Element(求众数)
英文版:https://leetcode.com/problems/majority-element/
中文版:https://leetcode-cn.com/problems/majority-element/
Missing Positive(求缺失的第一个正数)
英文版:https://leetcode.com/problems/first-missing-positive/
中文版:https://leetcode-cn.com/problems/first-missing-positive/
链表
Linked List Cycle I(环形链表)
英文版:https://leetcode.com/problems/linked-list-cycle/
中文版:https://leetcode-cn.com/problems/linked-list-cycle/
Merge k Sorted Lists(合并 k 个排序链表)
英文版:https://leetcode.com/problems/merge-k-sorted-lists/
中文版:https://leetcode-cn.com/problems/merge-k-sorted-lists/
解答过程及代码
Three Sum (求三数之和)
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
排序+双指针:
先对数组进行排序,然后使用双指针从两头逼近,注意避免重复情况
源代码
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
nums.sort()
if not nums or n < 3:
return []
res = []
for i in range(n-1):
if i > 0 and nums[i] == nums[i-1]:
continue
l, r = i + 1, n - 1
while l < r:
s = nums[i] + nums[l] + nums[r]
if s > 0:
r = r - 1
elif s < 0:
l = l +1
else:
res.append((nums[i], nums[l], nums[r]))
while l < r and nums[l] == nums[l + 1]:
l += 1
while l < r and nums[r] == nums[r - 1]:
r = r - 1
l = l + 1
r = r - 1
return res
Majority Element(求众数)
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例1
输入: [3,2,3]
输出: 3
示例2
输入: [2,2,1,1,1,2,2]
输出: 2
思路
法1:使用python的内建函数,统计数组中的元素及出现的个数,然后返回出现次数最多的元素;
法2:对数组排序,中间位置的数一定是众数
源代码1
class Solution:
def majorityElement(self, nums: List[int]) -> int:
counts = collections.Counter(nums)
return max(counts.keys(), key = counts.get)
源代码2
class Solution:
def majorityElement(self, nums: List[int]) -> int:
nums.sort()
# 中间的位置一定是众数
return(mums[len(nums)//2]
Missing Positive(求缺失的第一个正数)
给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。
示例1
输入: [1,2,0]
输出: 3
示例2
输入: [3,4,-1,1]
输出: 2
示例3
输入: [7,8,9,11,12]
输出: 1
思路
循环判断 1-n 是否在数组中,若在则继续找下一个,不在则返回
注意:return与break语句的区别与联系
源代码
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n = len(nums)
if not nums:
return 1
# 酷酷的代码
# i 不在说明就是最小正整数
for i in range(1, n+1):
if i not in nums:
return i
#if 语句下不需要加break语句吗???
# 测试结果是加不加都可以通过
return n+1
Linked List Cycle I(环形链表)
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
思路
快慢指针方法:设定快慢指针,快指针每次移动两个元素,慢指针移动一个元素。若有环,慢指针一定会与快指针相遇,否则无环。
注意:快慢指针的设定方法,书写规范
源代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: ListNode) -> bool:
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
Merge k Sorted Lists(合并 k 个排序链表)
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下: [ 1->4->5, 1->3->4, 2->6 ] 将它们合并到一个有序链表中得到。 1->1->2->3->4->4->5->6
示例 2:
输入:lists = []
输出:[]
示例 3:
输入:lists = [[]]
输出:[]
思路
分治思想,递归调用
源代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
n = len(lists)
if n == 0: return None
if n == 1: return lists[0]
if n == 2: return self.mergeTwoLists(lists[0], lists[1])
mid = n // 2
# 这一句写错了无数次,不是多写字母就是大小写不太对
return self.mergeTwoLists(self.mergeKLists(lists[:mid]), self.mergeKLists(lists[mid:n]))
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
res = ListNode(0)
c1, c2, c3 = l1, l2, res
while c1 or c2:
if c1 and c2:
if c1.val < c2.val:
c3.next = ListNode(c1.val)
c1 = c1.next
else:
c3.next = ListNode(c2.val)
c2 = c2.next
c3 = c3.next
elif c1:
c3.next = c1
break
else:
c3.next = c2
break
return res.next