攻克 LeetCode 445、340、312、309 和 300,成为算法高手!
2023-11-23 01:17:59
LeetCode 445:两数相加 II
题目
给你两个非空链表来表示两个非负整数。数字最高位位于链表开头。这些数组中可能包含多余的 0。代表这两个数相加的值。
解题方法:
使用双指针从两个链表的末尾开始比较,将每一位上的数字相加,并将进位记录下来。如果某一个链表已经遍历完毕,则将另一个链表剩余的数字依次加入结果链表。
时间复杂度:
O(n),其中 n 是两个链表的总长度。
代码示例:
def addTwoNumbers(l1, l2):
dummy = ListNode(0)
current = dummy
carry = 0
while l1 or l2 or carry:
val1 = l1.val if l1 else 0
val2 = l2.val if l2 else 0
total = val1 + val2 + carry
carry = total // 10
current.next = ListNode(total % 10)
current = current.next
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
return dummy.next
LeetCode 340:至多包含 K 个不同字符的最长子串
题目:
给定一个字符串,请你找出其中不含有超过 K 个不同字符的最长子串。
解题方法:
使用滑动窗口法,维护一个滑动窗口,并记录窗口中不同字符的个数。当窗口中的不同字符个数大于 K 时,将窗口右端指针向左移动,直到窗口中不同字符的个数小于或等于 K。当窗口中的不同字符个数小于或等于 K 时,将窗口左端指针向右移动,直到窗口中不同字符的个数等于 K。
时间复杂度:
O(n),其中 n 是字符串的长度。
代码示例:
def longestSubstring(s, k):
max_len = 0
char_count = {}
for i in range(len(s)):
char_count[s[i]] = char_count.get(s[i], 0) + 1
while len(char_count) > k:
char_count[s[i - max_len]] -= 1
if char_count[s[i - max_len]] == 0:
del char_count[s[i - max_len]]
max_len += 1
return len(s) - max_len
LeetCode 312:戳气球
题目:
有 n 个气球,每个气球都有一定的分值。你可以在任何时候戳破一个气球,并得到该气球的分值。但戳破一个气球后,相邻两个气球的分值都会变成 0。求戳破所有气球能得到的最大分值。
解题方法:
使用动态规划法,定义状态 dp[i][j] 表示戳破从第 i 个气球到第 j 个气球能得到的最大分值。然后根据状态转移方程 dp[i][j] = max(dp[i][k] + dp[k + 1][j] + nums[i] * nums[k + 1] * nums[j]) 更新状态。
时间复杂度:
O(n^3),其中 n 是气球的个数。
代码示例:
def maxCoins(nums):
nums = [1] + nums + [1]
n = len(nums)
dp = [[0] * n for _ in range(n)]
for length in range(2, n):
for i in range(n - length):
j = i + length
for k in range(i + 1, j):
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + nums[i] * nums[k + 1] * nums[j])
return dp[0][n - 1]
LeetCode 309:最佳买卖股票时机含冷冻期
题目描述:
给你一个整数数组 prices,其中 prices[i] 是某一天股票的价格。你只能连续两天买卖股票,之后你必须等待 冷冻期 才能再次买卖股票。求在冷冻期内能获得的最大利润。
解题方法:
使用动态规划法,定义状态 dp[i][0] 和 dp[i][1] 分别表示在第 i 天持有股票和不持有股票的最大利润。然后根据状态转移方程 dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]) 和 dp[i][1] = max(dp[i - 1][1], dp[i - 2][0] - prices[i]) 更新状态。
时间复杂度:
O(n),其中 n 是天数的个数。
代码示例:
def maxProfit(prices):
n = len(prices)
dp = [[0] * 2 for _ in range(n)]
for i in range(n):
if i == 0:
dp[i][0] = -prices[i]
else:
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
dp[i][1] = max(dp[i - 1][1], dp[i - 2][0] - prices[i])
return dp[n - 1][0]
LeetCode 300:最长递增子序列
题目描述:
给你一个整数数组 nums,请你找出其中最长的递增子序列。
解题方法:
使用动态规划法,定义状态 dp[i] 表示以第 i 个数字结尾的最长递增子序列的长度。然后根据状态转移方程 dp[i] = max(dp[j] + 1) 更新状态,其中 j < i 且 nums[j] < nums[i]。
时间复杂度:
O(n^2),其中 n 是数组的长度。
代码示例:
def longestIncreasingSubsequence(nums):
n = len(nums)
dp = [1] * n
for i in range(1, n):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
总结
通过对 LeetCode 445、340、312、309 和 300 这五个经典题目的详细讲解,相信读者们已经对这些题目的解法和技巧有了更加深入的了解。希望这些题目的讲解能够帮助读者们提高算法和编程能力,成为算法高手!