力扣(LeetCode)是一个在线编程平台,主要用于帮助程序员提升算法和数据结构方面的能力。以下是一些力扣上的入门题目,以及它们的解题代码。
--点击进入刷题地址
1. 两数之和
题目描述:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9
所以 返回 [0, 1]
def twoSum(nums, target): num_dict = {} for i, num in enumerate(nums): if target - num in num_dict: return [num_dict[target - num], i] num_dict[num] = i return None
小结:
- 两数之和:考察了如何通过遍历数组两次来找到和为目标值的两个数。关键在于使用一个字典来存储已遍历过的数和它们的索引,以避免重复计算。
2. 合并两个有序链表
题目描述:
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->2->3->4
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def mergeTwoLists(l1: ListNode, l2: ListNode) -> ListNode: dummy = ListNode(0) # 创建一个虚拟头节点作为新链表的头部 curr = dummy # 当前节点指针,初始指向虚拟头节点 while l1 and l2: # 当两个链表都有节点时,比较大小并添加到新链表中 if l1.val < l2.val: curr.next = l1 # 当前节点指向l1,将l1向后移动一个节点,指向下一个节点 l1 = l1.next # l1向后移动一个节点 else: # 如果l2.val < l1.val,同理处理l2和l1的关系 curr.next = l2 # 当前节点指向l2,将l2向后移动一个节点,指向下一个节点 l2 = l2.next # l2向后移动一个节点 curr = curr.next # 当前节点向后移动一个节点,指向下一个节点(刚刚添加的节点) curr.next = l1 if l1 else l2 # 如果其中一个链表已经遍历完,将另一个链表的剩余部分添加到新链表中 return dummy.next # 返回新链表的头部(虚拟头节点的下一个节点)
小结:
- 合并两个有序链表:这道题考察了如何通过比较节点值的大小来合并两个升序链表。我们维护一个当前节点指针,并根据链表节点的值来决定下一个节点。
3. 最长回文子串(动态规划)
描述:
给定一个字符串s,找到s中最长回文子串的长度。
示例:
给定字符串为"babad",返回3,因为最长的回文子串是"aba"。
代码实现:
def longestPalindromeSubseq(s: str) -> int: n = len(s) dp = [[0] * n for _ in range(n)] for length in range(1, n+1): for i in range(n-length+1): j = i + length - 1 if s[i] == s[j]: if length == 2: dp[i][j] = 1 else: dp[i][j] = dp[i+1][j-1] + 2 else: dp[i][j] = max(dp[i+1][j], dp[i][j-1]) return dp[0][n-1]
解题思路:
动态规划是解决这个问题的有效方法。我们可以定义一个二维数组dp,其中dp[i][j]表示s中从索引i到索引j的子串是否为回文串。对于dp[i][j],如果s[i] == s[j]且dp[i+1][j-1]为true,那么dp[i][j]也为true。我们可以从长度为1的子串开始,逐渐增加子串的长度,直到达到整个字符串的长度。在每个阶段,我们只需要考虑以当前字符为中心的子串是否为回文串,并更新dp数组的值。最后,dp数组中的最大值即为所求的最长回文子串的长度。
小结:
- 最长回文子串:这道题是关于动态规划的经典问题。我们使用一个二维数组dp来保存中间状态,并根据字符串的特性更新dp数组的值。最后返回dp数组中的最大值即可。