002 两数相加
链接: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 = [0], l2 = [0]
输出:[0].
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
提示:
- 每个链表中的节点数在范围 [1, 100] 内
- 0 <= Node.val <= 9
- 题目数据保证列表表示的数字不含前导零
思路
模仿加法运算。个位相加超过十进一,十位相加有进位则加上进位,依次类推。
同时考虑两种特殊情况:
1.长度不相等 123 + 45678
2.有进位的情形 11 + 99 = 110
代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 创建一个结点值为None的头结点,dummy和p指向头结点,dummy用来最后返回,p用来遍历
dummy=p=ListNode(None)
s=0 # 初始化进位s为0
while l1 or l2 or s:
# 如果l1或l2存在,则取l1的值+l2的值+s(s初值为0,如果下面有进位1,下次加上)
s+=(l1.val if l1 else 0)+(l2.val if l2 else 0)
p.next=ListNode(s%10) # p.next指向新链表,用来创建一个新的链表
p=p.next # p向后遍历
s//=10 # 有进位情况则取模,例如s=18,18//10=1
l1=l1.next if l1 else None # 如果l1存在,则向后遍历,否则为None
l2=l2.next if l2 else None # 如果l2存在,则向后遍历,否则为None
return dummy.next # 返回dummy的下一个节点,因为dummy指向的是空的头结点
学习记录
-
val() 函数语法为:
i. val(字符表达式)
val() 函数的功能为:将一组字符型数据的数字部分转换成相应的数值型数据
val() 函数用法:
例 x = "125fdsa DA456"; val(x)应该返回125 后面的456不能返回来。
val() 函数当识别到非数字,停止读入字符串。
即如果字符串内有字母或其他非数字字符,val()函数只转换第一个非数字字符之前的数字。
当字符串的首字符为非数字时,返回值为0。但是该函数可以识别进制符号比如八进制、十六进制。字符串中的空格和换行符也会从该参数中被去掉。
例 a = "五颗星"; b = 3; 当进行运算 a + b 时显然是错误的。
若想得到返回值为8,就要使用 val()函数
c = val(a) + b; 此时c的值为8。
ii. Val(C, V, Site)
功能为:将字符串C转换成与V相同的数值类型,并把转换后的结果赋值给V,如果字符串中有非数字,则V=0。Site用于返回非数字字符的位置。
004 寻找两个正序数组的中位数
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
题目
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。
进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
示例 3:
输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
示例 4:
输入:nums1 = [], nums2 = [1]
输出:1.00000
示例 5:
输入:nums1 = [2], nums2 = []
输出:2.00000
提示:
- nums1.length == m
- nums2.length == n
- 0 <= m <= 1000
- 0 <= n <= 1000
- 1 <= m + n <= 2000
- -10^6<= nums1[i], nums2[i] <= 10^6
思路
首先把两个有序数组合并为一个有序数组,然后根据数组长度来确定中位数,如果数组长度为偶数,那么返回两个中位数的平均值,如果数组长度为奇数,那么返回中位数。
代码
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
s=nums1+nums2
s.sort()
if len(s) % 2 == 0:
index=len(s)//2
return (s[index]+s[index-1])/2
else:
index=(len(s)-1)//2
return s[index]
学习记录
还有一个二分查找的方法。之后再补上。
005 最长回文子串
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/
题目
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
示例 3:
输入:s = “a”
输出:“a”
示例 4:
输入:s = “ac”
输出:“a”
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母(大写和/或小写)组成
思路
设我们的输入字符串为s:
1.构造二维矩阵dp,维度为len(s)*len(s),dp[i][j]表示子串s[i:j+1]是否为回文串,i和j均为下标索引,范围在0~len(s)之间,且i<j,因此dp矩阵中的每一个变量均为布尔量;
2.构造状态转移方程,考虑三种情况,
(1)i = j,当前子串只有一个字符,一定为回文串;
(2)j= i+ 1,当前子串只有两个字符,判断这两个字符是否相等;
(3)j> i+ 1,当前子串有多个字符,判断根据首位字符是否相等以及除去首位字符剩余子串是否为回文串判定当前子串。
状态转移方程为:
d
p
[
i
]
[
j
]
=
{
T
r
u
e
,
i
=
j
s
[
i
]
=
=
s
[
j
]
,
j
−
i
=
1
s
[
i
]
=
=
s
[
j
]
a
n
d
d
p
[
i
+
1
]
[
j
−
1
]
,
j
−
i
>
1
dp[i][j] = \begin{cases} True, & \text{$i=j$} \\ s[i]==s[j], & \text{$j-i=1$} \\ s[i]==s[j] and dp[i+1][j-1], & \text{$j-i>1$} \\ \end{cases}
dp[i][j]=⎩⎪⎨⎪⎧True,s[i]==s[j],s[i]==s[j]anddp[i+1][j−1],i=jj−i=1j−i>1
或者把前两者归类:
d
p
[
i
]
[
j
]
=
{
s
[
i
]
=
=
s
[
j
]
,
j
−
i
<
=
1
s
[
i
]
=
=
s
[
j
]
&
d
p
[
i
+
1
]
[
j
−
1
]
,
j
−
i
>
1
dp[i][j] = \begin{cases} s[i]==s[j], & \text{$j-i<=1$} \\ s[i]==s[j]\ \& \ dp[i+1][j-1], & \text{$j-i>1$} \\ \end{cases}
dp[i][j]={s[i]==s[j],s[i]==s[j] & dp[i+1][j−1],j−i<=1j−i>1
代码
class Solution:
def longestPalindrome(self, s):
dp = [[False]*len(s) for _ in range(len(s))]
max_start, max_len = 0, 0 # 最长回文子串开始位置及长度
for j in range(len(s)): # j指针先走
for i in range(j+1): # i指针跟着j指针
if j - i < 2: # 前两种情况
dp[i][j] = (s[i] == s[j])
else: # 最后一种情况
dp[i][j] = (s[i] == s[j]) and dp[i+1][j-1] # 状态转移方程
# cur_substr = s[i:j+1] # 当前考察的子串
cur_len = j + 1 - i # 当前子串长度为 j + 1 - i
if dp[i][j] and max_len < cur_len:
max_start = i
max_len = cur_len
return s[max_start:max_start + max_len]
学习记录
关于动态规划(by: liweiwei1419)
参考:
1.https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/
2.https://www.jianshu.com/p/6f226c9180e2