力扣学习笔记 day1

题002

题意

给定两个非空链表,分别表示两个非负整数,每位数字按逆序存储,每个节点表示一位数字。将两个链表表示的数相加,并以同样的方式输出。

eg.

输入: l1 = [2,4,3], l2 = [5,6,4]
输出: [7,0,8]
解释: 342 + 465 = 807.

示意图

提示

  • 每个链表中的节点数在范围 [1, 100]
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

解题思路

  • 因为链表的第一位是个位,以此类推,所以将两个链表从第一位开始相加,和除以十,判断进位(tmp),余数留下。
  • 具体的操作有两种方法:
  • 法一:
    • 将更长的那个链表(假设是l1)作为返回的链表,将和的值加到l1上
    • 创造一个递归函数,根据不同的条件进行操作,具体的判断如下方流程图所示(节点的值相加完成后)
都存在
tmp存在
l1存在
l1和l2都存在
递归
l2更长
交换l1和l2
判断l1和tmp的存在
将进位值和l1相加
新增节点
输出结果
  • 法二:
    • 创建新的链表,每一位计算后赋值到当前node并建立新的node
    • 将l1,l2和进位值三者作为while循环的条件,当l1和l2中的任一个不存在时,赋值为None,计算时加零
  • 当不再存在进位或者链表遍历结束时,输出结果。

代码

法一

class Solution:
	def addTwoNumbers(self,l1:ListNode,l2:ListNode)->ListNode:
		def sum(l1,l2,tmp):
			tmp+=l1.val+l2.val
			l1.val=tmp%10 #将余数赋值到当前节点
			tmp//=10 #tmp整除10后得到进位值
			if l1.next and l2.next:
				return sum(l1.next,l2.next,tmp)
			if l2.next:#如果l2更长,l1,l2互换
				l1.next=l2.next
			while l1.next and tmp:
				l1=l1.next
				tmp+=l1.val
				l1.val=tmp%10
				tmp//=10
			if tmp:
				l1.next=ListNode(1)
		
		sum(l1,l2,0)
		return l1

法二

class Solution:
	def addTwoNumbers(self,l1:ListNode,l2:ListNode)->ListNode:
		cur=head=ListNode(None)
		tmp=0 
		while l1 or l2 or tmp:
			tmp+=(l1.val if l1 else 0)+(l2.val if l2 else 0)
			cur.next=ListNode(tmp%10)#创建新节点
			tmp//=10
			cur=cur.next
			l1 = l1.next if l1 else None
			l2 = l2.next if l2 else None
		return head.next

题004

题意

给定两个大小为m和n的正序数组nums1和nums2,请找出这两个数组合并后的中位数。
要求:时间复杂度控制在O(log(m+n))

eg

输入: nums1 = [1,3], nums2 = [2]
输出: 2.00000
解释: 合并数组 = [1,2,3] ,中位数 2

输入: nums1 = [1,2], nums2 = [3,4]
输出: 2.50000
解释: 合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

提示

  • nums1.length == m
  • nums2.length == n
  • 0 <= m <= 1000
  • 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -106 <= nums1[i], nums2[i] <= 106

解题思路

题意要求时间复杂度控制在O(log(m+n)),如果我们用第一反应将两个数组合并后排序,那么时间复杂度将达到O(m+n),所以参考了各种题解后,我觉得寻找第k小的数这种方法比较值得学习,而且这个方法适用性范围比较广

题目中为两个正序数组,要找中位数,利用题解中讲到的寻找第k个数的方法,就是删除前二分之一的数。

做法是每次循环,删除前一般的数的前面一半,也就是对于前一半的数,每次保留后1/2, 这样最后只剩下了一个数,即中位数。

具体的做法:

  • 每次删除完后,两个数组的长度会变化,为了方便操作,每次删除后确保nums1比nums2长
  • 删除范围t的大小视具体情况而定,取较短数组的长度和k/2中更小的一个: t=min(k//2,len(l2))]
  • 对于k个数的中位数
    • 若k=2m+1,中位数为第m+1个
    • 若k=2m,中位数为第m和m+1个的平均值
  • 所以求k个数中第(k+1)//2和第k//2+1个数,再取平均数
    • 若k=2m+1,取到的是第m+1个和第m+1个
    • 若k=2m,取到的是第m个和第m+1个

代码

def findMedianSortedArrays(self, nums1: List\[int\], nums2: List\[int\]) -> float:
 	def findk(l1,l2,k):
		if len(l1)<len(l2):
		 	l1,l2=l2,l1
		if len(l2)==0:
			return l1[k-1]
		if k==1:
			return min(l1[0],l2[0])
		t=min(k//2,len(l2))#确定删除范围的大小
		if l1[t-1]<l2[t-1]:
			return findk(l1[t:],l2,k-t)
		else:
			return findk(l1,l2[t:],k-t)
	#取两个数然后求平均值
	k1=(len(nums1)+len(nums2)+1)//2
	k2=(len(nums1)+len(nums2)+2)//2
	return (findk(nums1,nums2,k1)+findk(nums1,nums2,k2))/2

题005

题意

给定一个字符串,找出其中的最长的回文子串。

eg.

输入: s = “babad”
输出: “bab”
解释: “aba” 同样是符合题意的答案。


解题思路

  • 还是采取遍历的方式,从头开始,寻找最长的回文子串
  • 考虑到回文字符串的格式
    • 如果长度为奇数,那么中心为一个字符
    • 如果长度为偶数,那中心是两个相同的字符
  • 所以遍历时,以当前节点为中心,分两种情况(偶数节点和奇数节点)向外扩张,寻找最长的回文子串
def expand(s,l,i,j):
	while i>=0 and j<l and s[i]=s[j]:
		i-=1
		j+=1
	return s[i+1:j],j-1-1
  • 每个节点搜寻完成后和当前最长子串的长度进行比较,保留更长的

代码

class Solution:
	def longestPalindrome(self, s:str)->str:
		#定义一个扩展字符串的函数
		def expand(s,l,i,j):
			while i>=0 and j<l and s[i]==s[j]:
				i-=1
				j+=1
			return s[i+1:j],j-i-1
		
		l=len(s)
		if l<2:
			return s
		maxl=1
		res=s[0]#以防没有回文子串
		
		for i in range(l):
			s1,l1=expand(s,l,i,i)
			s2,l2=expand(s,l,i,i+1)
			
			cur=s1 if l1>l2 else s2
			if len(cur)>maxl:#若发现了更大的回文子串
				maxl=len(cur)
				res=cur
		return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值