题目一
题目
给定两个大小为 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、我的想法比较简单,直接将两个数组相连,然后对数组排序,位于中间的一个(或两个的平均数)即为中位数,代入如下:
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
nums3 = nums1 + nums2
nums3.sort()
l = len(nums3)
if l % 2 == 1:
return nums3[l // 2]
else:
return (nums3[l//2]+nums3[l//2-1])/2
突然想起来排序是python里面数组自带的函数,对于其他语言可能没有这样的函数,这种投机的方法就行不通了。
2、后来想可以通过归并排序的思想来实习手动排序,因为题目中说了nums1和nums2是有序数组,只需执行最后一步合并就行,代码如下:
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
nums3=[]
i, j = 0, 0
while (i < len(nums1) and j < len(nums2)):
if nums1[i] <= nums2[j]:
nums3.append(nums1[i])
i += 1
else:
nums3.append(nums2[j])
j += 1
nums3 += list(nums1[i:])
nums3 += list(nums2[j:])
l = len(nums3)
if l % 2 == 1:
return nums3[l//2]
else:
return (nums3[l//2]+nums3[l//2-1])/2
题目二
题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
我的解答
1、简单粗暴的想法:列出所有的子串,然后判断是不是回文,结果不出意外的超时了?(为什么我的第一想法总是那么简单粗暴),代码如下:
class Solution:
def longestPalindrome(self, s):
max_len = 0
max_str = ''
l = len(s)
for i in range(l):
for j in range(i+1, l+1):
if self.palindrome(s[i:j]): # 子序列
if j-i > max_len:
max_len = j-i
max_str = s[i:j]
return max_str
def palindrome(self, s): # 检查是否为回文序列
l = len(s)
for i in range(l//2):
if s[i] != s[l-i-1]:
return False
return True
2、判断回文:从某个位置开始,往两边移动指针,看字符是否相同,这样只需遍历一遍字符串,代码如下:
class Solution:
def longestPalindrome(self, s):
start = 0
end = 0
for i in range(len(s)):
len1 = self.palindrome(s, i, i)
len2 = self.palindrome(s, i, i+1) # 判断两个相同字符
length = max(len1, len2)
if length > end - start:
start = i - (length-1)//2
end = i + length//2
return s[start:end+1]
def palindrome(self, s, j, k):
max_len = 0
while (j>=0 and k<len(s) and s[j] == s[k]):
j -= 1
k += 1
if max_len < k-j-1:
max_len = k-j-1
return max_len
题目三
题目
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”
示例 2:
输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释:
L D R
E O E I I
E C I H N
T S G
我的解答
1、这道题其实不难,主要是找出其中的规律,表明上看是字符的排列,其实可以直接看成字符下标的排列,进而转换成数字的排列,这样找规律就简单一些。由题目中的两个例子可以看出:第一行的数都差了2*numRows-2,最后一行也是,其实中间行竖排的部分也是,而中间行的其余元素与行数有关。因此可以如下代码:
class Solution:
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
s1 = ''
for j in range(numRows):
for i in range(len(s)):
if i%(2*numRows-2)==j or i%(2*numRows-2)==2*numRows-2-j:
s1 += s[i]
return s1
悲剧的是还是超时了,看来以后真的需要好好注意程序运行的效率了。
2、前面的代码效率太低,主要是因为前面每次都需要遍历一遍,从中找出余数为行数的数字,换个角度想,每一行从行号开始,选出间隔为step的数,对于该行的其他数,可以看出它们的规律为j+step-2*i。因此代码如下:
class Solution:
def convert(self, s, numRows):
if numRows == 1:
return s
elif numRows > len(s):
return s
s1 = ''
step = 2*numRows - 2
for i in range(numRows):
for j in range(i, len(s), step):
s1 += s[i]
if i!=0 and i!=numRows-1 and j+step-2*i<len(s): # 找出每一行处于斜位置的数
s1 += s[j+step-2*i]
return s1