4. 两个排序数组的中位数
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。
请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。
示例 1:
nums1 = [1, 3] nums2 = [2] 中位数是 2.0
示例 2:
nums1 = [1, 2] nums2 = [3, 4] 中位数是 (2 + 3)/2 = 2.5
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
a = []
m = len(nums1)
n = len(nums2)
i = 0#nums1的位置
j = 0#nums2的位置
while len(a) <= (m + n)/2:
if(i == m):
a.extend(nums2[j:])
break
if(j == n):
a.extend(nums1[i:])
break
s = min(nums1[i],nums2[j])
a.append(min(nums1[i],nums2[j]))
if(nums1[i] < nums2[j]):
i += 1
else:
j += 1
if (m + n)% 2 == 0:
median = (a[int((m + n)/2 - 1)] + a[int((m + n)/2)])/2
else:
median = a[int((m + n)/2)]
return float(median)
思路:建立一个新的序列 逐一按顺序把nums1,nums2的数字加入序列,生成到中位数位置时停止
5. 最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:
输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案。
示例 2:
输入: "cbbd" 输出: "bb"
class Solution:
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
maxlen = 0
start = 0
p = [[0 for i in range(len(s))] for i in range(len(s))]
for index in range(len(s)):
p[index][index] = 1
if (index < len(s) -1 and s[index] == s[index + 1]):
p[index][index + 1] = 1
start = index
maxlen = 1
for length in range(2,len(s)):
for index in range(len(s)-length):
if(s[index] == s[index + length]):
p[index][index + length] = p[index + 1][index + length - 1]
if(p[index][index + length] == 1):
maxlen = max(maxlen,length)
start = index
else:
p[index][index + length] = 0
return s[start:start + maxlen + 1]
二维数组建立:
p = [[0 for i in range(len(s))] for i in range(len(s))]
思路:动态规划 转移方程:if s[i] == s[j] :p[i][j] = p[i+1][j-1]
else: p[i][j] = 0
时间复杂度为O(n^2)
另有一种时间复杂度为O(n)的方法:
Manacher算法
1.思想:
1)将原字符串S的每个字符间都插入一个永远不会在S中出现的字符(本例中用“#”表示),在S的首尾也插入该字符,使得到的新字符串S_new长度为2*S.length()+1,保证Len的长度为奇数(下例中空格不表示字符,仅美观作用);
例:S: a a b a b b a
S_new: # a # a # b # a # b # b # a #
2)根据S_new求出以每个字符为中心的最长回文子串的最右端字符距离该字符的距离,存入Len数组中,即S_new[i]—S_new[r]为S_new[i]的最长回文子串的右段(S_new[2i-r]—S_new[r]为以S_new[i]为中心的最长回文子串),Len[i] = r - i + 1;
S_new: # a # a # b # a # b # b # a #
Len: 1 2 3 2 1 4 1 4 1 2 5 2 1 2 1
Len数组性质:Len[i] - 1即为以Len[i]为中心的最长回文子串在S中的长度。在S_new中,以S_new[i]为中心的最长回文子串长度为2Len[i] - 1,由于在S_new中是在每个字符两侧都有新字符“#”,观察可知“#”的数量一定是比原字符多1的,即有Len[i]个,因此真实的回文子串长度为Len[i] - 1,最长回文子串长度为Math.max(Len) - 1。
3)Len数组求解(线性复杂度(O(n))):
a.遍历S_new数组,i为当前遍历到的位置,即求解以S_new[i]为中心的最长回文子串的Len[i];
b.设置两个参数:sub_midd = Len.indexOf(Math.max(Len)表示在i之前所得到的Len数组中的最大值所在位置、sub_side = sub_midd + Len[sub_midd] - 1表示以sub_midd为中心的最长回文子串的最右端在S_new中的位置。起始sub_midd和sub_side设为0,从S_new中的第一个字母开始计算,每次计算后都需要更新sub_midd和sub_side;
c.当i < sub_side时,取i关于sub_midd的对称点j(j = 2sub_midd - i,由于i <= sub_side,因此2sub_midd - sub_side <= j <= sub_midd);当Len[j] < sub_side - i时,即以S_new[j]为中心的最长回文子串是在以S_new[sub_midd]为中心的最长回文子串的内部,再由于i、j关于sub_midd对称,可知Len[i] = Len[j];
当Len[j] >= sub.side - i时说明以S_new[i]为中心的回文串可能延伸到sub_side之外,而大于sub_side的部分还没有进行匹配,所以要从sub_side+1位置开始进行匹配,直到匹配失败以后,从而更新sub_side和对应的sub_midd以及Len[i];
d.当i > sub_side时,则说明以S_new[i]为中心的最长回文子串还没开始匹配寻找,因此需要一个一个进行匹配寻找,结束后更新sub_side和对应的sub_midd以及Len[i]。
2.时间复杂度解释:
算法只有遇到还没匹配的位置时才进行匹配,已经匹配过的位置不再进行匹配,因此大大的减少了重复匹配的步骤,对于S_new中的每个字符只进行一次匹配。所以该算法的时间复杂度为O(2n+1)—>O(n)(n为原字符串的长度),所以其时间复杂度依旧是线性的。
7. 反转整数
给定一个 32 位有符号整数,将整数中的数字进行反转。
示例 1:
输入: 123 输出: 321
示例 2:
输入: -123 输出: -321
示例 3:
输入: 120 输出: 21
注意:
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。根据这个假设,如果反转后的整数溢出,则返回 0。
class Solution:
def reverse(self, x):
"""
:type x: int
:rtype: int
"""
a = str(abs(x))
b = a[::-1]
c = int(b)
if(x > 0 and c <= pow(2,31) - 1):
return c
elif (x < 0 and c <= pow(2,31)):
return -c
else:
return 0
[::-1]反转列表