python实现
一、字符串转成整数
开头可能是空格、’+’、’-’、‘数字’、‘字母’,
但是遇到字母字符就要停止,或者开头是‘±’也要停止。
还要注意溢出问题;对于空格允许多个所以可以用循环跑完,也可以直接使用字符串方法strip()
def strToint(s):
if not s:
return 0
max_num, min_num = 2**31 - 1, -2**31
length = len(s)
# 为获取字符里对应数字
char_num = ['0','1','2','3','4','5','6','7','8','9']
# 用来判断正负
sign = ['+','-']
flag = 1
i = 0
while s[i] == ' ':
i += 1
if i == length:
return
if s[i] in sign:
if s[i] == '-':
flag = -1
# 用来记录返回的整数
ret = 0
for j in range(i,length):
if s[j] in char_num:
# 判断是否溢出 这个地方ret只是正数
if ret > max_num // 10 or (ret == max_num and s[j] > '7'):
return max_num if flag == 1 else min_num
# 索引和其值正好对应,并且还是int型
ret = ret*10 + char_num.index(s[j])
#因为前面的情况都已经判断结束(从i开始的),一旦遇到不是数字,直接跳出
else:
break
return ret*flag
二、反转整数
实现起来很简单,思路就是求余获取整数的每一位,然后循环按照十进制加法反转,但是需要注意几点1、参数的正负值;2、溢出返回0
def convert(x):
flag = 1
if x < 0:
x = -x
flag = -1
ret = 0
max_num, min_num = 2**31 - 1, -2**31
while x:
num = x % 10
x = x // 10
if ret > max_num //10 or (ret == max_num // 10 and num > 7):
return 0
ret = ret * 10 + num
return ret*flag
三、字符串Z型排列打印
问题:字符串s按照上下指定numRow行这样Z型排列,要求按照每行从左到
右读取;
首先可以看做是两层循环,因为有numRow行,所以外层相当于循环
numRow次,每次增加1,内部循环首先循环次数是和字符换长度有关,每次
起始位置是和行数有关的,其次就是要判断每行相邻的两个数之间的间距即循环变量步长。
主要针对两个数距离问题分析:不难发现首尾两行两数A和B之间相隔的数有 2numRow - 3 个,
但是其他行对于相距 2numRow - 3 个数里面还有一个数C,这个C与B之间间隔可以通过行数知道2*i -1,i= 1,…,numRow。(i=0不需要这样算)
def charZprint(s,numRow):
if not s:
return
res = ''
# 之间间隔数是 2*numRow - 3 ,但是获得后面那个数索引需要再加1
gap = 2*numRow - 2
n = len(s)
for i in range(numRow):
j = 0
while j + i < n :
ret += s[j+i]
# 获取C的索引 gap - 2*i + j + i (j+i是起始,gap - 2*i 间隔+1)
if i != 0 and i != numRow -1 and gap + j - i < n:
ret += s[gap + j - i]
j += gap
return ret
四、回文子串
一个回文子串去掉首尾字符仍然是回文子串,这样我们就是以长度为1或2两左右扩展并记录对应长度,最终返回最长子串。
def longest_str(s):
if not s:
return 0
n = len(s)
start, end = 0, 0
def find(left,right):
while left >=0 and right < n and s[left] == s[right]:
left -= 1
right += 1
return left + 1, right - 1
for i in range(n):
# 下面相当于分别以长度为1和2为扩展
left1, right1 = find(i,i)
left2, right2 = find(i,i+1)
if right1 - left1 > end - start:
start, end = left1, right1
if right2 - left2 > end - start:
start, end = left2, right2
return s[startL:end+1]
五、两个有序数组的中位数
思路1:两个有序数组使用一次归并排序,合并数组长度L若是偶数,则第L//2个数和第L//2+1
个数平均值即为所求中位数,若是奇数,则第(L+1)//2个数是中位数。
思路2:二分查找;L为偶数时,假设第k小的数为中位数,第一个数组array1的长度为m,第二个数组array2的长度
是n,,比较 array1[k//2-1] < array2[k//2-1],两个数组中小于等于 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个,那么对于两个数组array1[k//2-1]、array2[k//2-1]这个位置的最大元素是第k-1个。
数来说就不可能是合并后的中位数,反之,同理。
def getMidNum(array1,array2):
def find(k):
index1 = 0
index2 = 0
# 注意这个k一直记录是第几个数
while True:
if index1 == m:
return array2[index2 + k - 1]
if index2 == n:
return array1[index1 + k - 1]
if k == 1:
return min(array1[index1],array2[index2])
# 找到每个数组的需要比较的位置
newIndex1 = min(index1 + k//2 - 1, m-1)
newIndex2 = min(index2 + k//2 - 1, n-1)
if array1[newIndex1] <= array2[newIndex2]:
#去掉小的那个数的前面所有数,已经包括头尾所以要加个1
k -= newIndex1 - index1 + 1
index1 = newIndex1 + 1
else:
index2 = newIndex2 + 1
k -= newIndex2 - index2 + 1
m = len(array1)
n = len(array2)
L = m + n
if L%2 != 0:
return find((L+1)//2)
else:
return find(L//2 + L//2 + 1) / 2
六、数组跳跃问题
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
思路:数组可以到达下标y位置的前提是前面的位置存在一个位置i使得(i+nums[i])大于等
于y。只要前面n-1个位置存在一个x使得x+nums[x]大于等于下标n–1即可。
def jumpNum(nums):
n = len(nums)
max_step = 0
# 这个地方可以是n,因为只要到达位置n-2不是零必定可以到达n-1位置;如果是零也不影响最后的结果。
for i in range(n):
if max_step >= i:
max_step = max(max_step,i+nums[i])
if max_step >= n - 1:
return True
else:
return False