面经整理计划——第六弹

算法&&八股文&&其他


一、算法篇

  1. 输入一个长度为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
  1. 对于长度为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
  1. 给定一个整数数组 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]:
                    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值