算法&&八股文&&其他
一、算法篇
- 输入一个长度为n的整型数组nums,数组中的一个或连续多个整数组成一个子数组。求所有子数组的乘积的最大值。
1.子数组是连续的,且最小长度为1,最大长度为n
2.长度为1的子数组,乘积视为其本身,比如[4]的乘积为4
分析:简单题(lc121)
动态规划 :根据正负性进行分类讨论
考虑当前位置如果是一个负数的话,那么我们希望以它前一个位置结尾的某个段的积也是个负数,这样就可以负负得正,并且我们希望这个积尽可能「负得更多」,即尽可能小。如果当前位置是一个正数的话,我们更希望以它前一个位置结尾的某个段的积也是个正数,并且希望它尽可能地大。于是这里我们可以维护一个fmin (i)和fmax(i),它表示以第 i 个元素结尾的乘积最小和最大子数组的乘积,那么动态规划转移方程:
fmax(i) = max(nums[i], nums[i] * fmax(i-1), nums[i] * fmin(i-1));
fmin(i) = min(nums[i], nums[i] * fmax(i-1), nums[i] * fmin(i-1));
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# @param nums int整型一维数组
# @return int整型
#
class Solution:
def maxProduct(self , nums: List[int]) -> int:
lenth = len(nums)
minmul, maxmul = nums[0], nums[0]
ans = maxmul
for num in nums[1:]:
minmul, maxmul = min(num, minmul * num, maxmul * num), max(num, minmul * num, maxmul * num)
ans = max(ans, maxmul)
return ans
# write code here
- 对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。
分析:middle(lc5)
马拉车算法O(n)
线性的算法–Manacher,可以将动态规划情况下的复杂度由 n2 的复杂度降到线性。Manacher算法能将奇偶长度的子串归为一类,它在原字符串中插入特殊字符,例如插入#后原字符串变成’#3#5#5#3#4#3#2#1#’。现在我们对新字符串使用中心扩展发即可,中心扩展法得到的半径就是子串的长度。
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# @param A string字符串
# @return int整型
#
class Solution:
def getLongestPalindrome(self , A: str) -> int:
return Palindrome().getLongestPalindrome(A, len(A))
class Palindrome:
def getLongestPalindrome(self, A, n):
if n <= 1: return n
# 每个字符之间插入 #
ss = '$#' + '#'.join([x for x in A]) + '#`'
p = [1] * len(ss)
center = 0
mx = 0
max_str = ''
for i in range(1, len(p)-1):
if i < mx:
j = 2 * center - i # i 关于 center 的对称点
p[i] = min(p[j],mx-i)
# 尝试继续向两边扩展,更新 p[i]
while ss[i - p[i] ] == ss[i + p[i] ]: # 不必判断是否溢出,因为首位均有特殊字符,肯定会退出
p[i] += 1
# 更新中心
if i + p[i] - 1 > mx:
mx = i + p[i] - 1
center = i
# 更新最长串
if 2 * p[i]-1 > len(max_str):
max_str = ss[i - p[i]+1 : i + p[i]]
maxLen = len(max_str.replace('#', ''))
return maxLen
- 给定一个整数数组 nums ,其中可能包含重复元素,请你返回这个数组的所有可能子集。
返回的答案中不能包含重复的子集,将答案按字典序进行排序。
分析:middle(nc221)
回溯 :考虑递归函数backtrack(start, temp),其功能是:
对于起点 start 元素,考虑在当前的 temp 基础上,将从start开始到数组末尾的所有元素都尝试在temp上添加一次,这样操作保证了字典序
O(n×2n),一共 2n 个状态,每个状态需要O(n)的时间代价来构造
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# @param nums int整型一维数组
# @return int整型二维数组
#
class Solution:
def subsets(self , nums: List[int]) -> List[List[int]]:
# write code here
res = []
nums.sort()
def backtrack(start, temp):
res.append(temp)
if start == len(nums):
return
for i in range(start, len(nums)):
if i > start and nums[i] == nums[i-1]: