题目1
- 题号:2
- 难度:中等
- https://leetcode-cn.com/problems/add-two-numbers/
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807
示例2:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
示例3:
输入:l1 = [0], l2 = [0]
输出:[0]
思路
模拟两个数相加,结果返回一个相加之后和的链表。
同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。具体而言,如果当前两个链表处相应位置的数字为 n1,n2,进位值为carry,则它们的和n1+n2+carry;其中,答案链表处相应位置的数字为 (n1+n2+carry)%10,而新的进位值为⌊n1+n2+carry⌋。
如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个 0 。
此外,如果链表遍历结束后,有carry>0,还需要在答案链表的后面附加一个节点,节点的值为 carry。
实现
# 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 addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = point = ListNode(0) # 定义链表头节点
carry = 0
while l1 or l2: #同时遍历这两个链表的节点
new_point = ListNode(0)
if not l1 : # l1节点为空的情况,把该节点的值当作0
res = l2.val+carry
new_point.val = res%10
carry = res // 10
l2=l2.next
elif not l2 : # l2节点为空的情况,把该节点的值当作0
res = l1.val + carry
new_point.val = res%10
carry = res // 10
l1=l1.next
else : # 两个节点都有值的情况
res = l2.val+l1.val+carry
# 两个节点的值相加的和与10取余为新节点
new_point.val = res % 10
# 进位值是除以10取整
carry = res // 10
# 同时指向下一个节点
l2=l2.next
l1=l1.next
# 把计算后的节点加在point的后面
point.next = new_point
# 指针往后移
point = point.next
# 遍历完所有节点后,判断最后一次循环时是否进位,即carry是否为1
if carry == 1 :
new_point = ListNode(1)
point.next = new_point
return head.next
分析
时间复杂度:O(max(m,n)),假设m和n分别表示l1和l2的长度,上面的算法最多重复max(m,n)次
空间复杂度:O(max(m,n)),新列表的长度最多为max(m,n) + 1
题目2
- 题号:4
- 难度:困难
- https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
思路1
首先把两个有序数组合并为一个有序数组,然后根据数组长度来确定中位数,如果数组长度为偶数,那么返回两个中位数的平均值,如果数组长度为奇数,那么返回中位数。
实现1
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
m = len(nums1)
n = len(nums2)
nums1.extend(nums2)# 合并
nums1.sort()# 排序
if (m + n) % 2 != 0:# 如果是奇数 返回中位数
return nums1[(m + n - 1)//2]
else:# 返回两个中位数的平均值
return (nums1[(m + n)//2 - 1] + nums1[(m + n)//2 ]) / 2
这个时间复杂度不符合 思路比较简单
思路2
二分查找(后续补一下 现在没看懂···)
题目3
- 题号:5
- 难度:中等
- https://leetcode-cn.com/problems/longest-palindromic-substring/
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
示例 3:
输入: "a"
输出: "a"
思路1
暴力法,列举所有的子串,判断该子串是否为回文
使用两个for循环遍历所有子串
实现1
执行结果:超出时间限制
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
if len(s) < 2:
return s
begin = 0
maxlen= 1
for i in range(len(s)-1):
for j in range(i+1,len(s)):
if ((j - i + 1) > maxlen) & (self.if_huiwen(s,i,j)):
maxlen = j - i + 1
begin = i
return s[begin:begin+maxlen]
def if_huiwen(self,s,left,right):
while left<right:
if s[left] != s[right]:
return False
left +=1
right -= 1
return True
分析1
时间复杂度:O(n^3)
空间复杂度:O(1)
思路2
动态规划:后续补上 之前没学过