剑指offer || 动态规划

剑指offer || 动态规划

剑指offer中有关动态规划的题目汇总


面试题14:剪绳子

题目:剪绳子

​ 给你一根长度为n的绳子,请把绳子剪成m段(m,n都是整数,n > 1 并且 m > 1), 每段绳子的长度记为k[0],k[1],…,k[m]。请问 k[0] * k[1]* …*k[m]可能的最大乘积是多少?

例子:当绳子的长度是8时,我们把它剪成长度为2、3 、3的三段,此时的最大乘积是18 `

思路

  • 动态规划

代码

#################面试题14#######################
#剪绳子
class Solution:
    def maxProdectAfterCutting_solution(self,length):
        product = []
        if length <2:
            return 0
        elif length == 2:
            return 1
        elif length == 3:
            return 2
        product.extend([0,1,2,3])
        max = 0
        for i in range(4,length+1):
            for j in range(1,i//2+1):
                area = product[j] * product[i-j]
                if max < area:
                    max = area
            product.append(max)
        return max

测试

################测试1#################
#功能测试
s = Solution()
s.maxProdectAfterCutting_solution(5)

面试题42:连续子数组的最大和

题目:连续子数组的最大和

​ 输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)

输入: 数组[1,-2,3,10,-4,7,2,-5],和最大的子数组为[3,10,-4,7,2]

输出:,因此输出该数组的和为18

思路

代码

#################面试题42#######################
#连续子数组的最大和

def FindGreatestSumOfSubArray(Array):
    if not Array:
        return 
    n = len(Array)
    maxSumArrayOfsubArray = [0] *(n+1)
    maxSum = float('-inf')
    for i in range(1,n+1):
        if maxSumArrayOfsubArray[i-1] <= 0:
            maxSumArrayOfsubArray[i] = Array[i-1]
        else:
            maxSumArrayOfsubArray[i] = maxSumArrayOfsubArray[i-1] + Array[i-1]
        if maxSum < maxSumArrayOfsubArray[i]:
            maxSum = maxSumArrayOfsubArray[i]
    return maxSum

测试

################测试1#################
#功能测试
#
Array = [1,-2,3,10,-4,7,2,-5]
result = FindGreatestSumOfSubArray(Array)
print(result)

Array = [-2,-3,-10,-4,-7,-2,-5]
result = FindGreatestSumOfSubArray(Array)
print(result)

Array = [2,3,10,4,7,2,5]
result = FindGreatestSumOfSubArray(Array)
print(result)

面试题47:礼物的最大价值

题目:礼物的最大价值

​ 在一个m*n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值,可以从棋盘的左上角开始拿格子里的礼物,并每次向左或右移动一格,直到到达棋盘的右下角。给定棋盘及其礼物,计算最多能拿到多少价值的礼物

例如:

1 10 3 8

12 2 9 6

5 7 4 11

3 7 16 5`

思路

  • 动态规划求解
  • f(i,j)=max(f(i1,j),f(i,j1))+gift[i,j] f ( i , j ) = m a x ( f ( i − 1 , j ) , f ( i , j − 1 ) ) + g i f t [ i , j ]

代码

#################面试题47#######################
#礼物的最大价值

def getMaxValue_solution1(values):
    if not values:
        return 0
    rows = len(values)
    if not isinstance(values[0], list):
        maxValue = sum(values)
        return maxValue
    else:
        cols = len(values[0])
    if cols == 1:
        maxValue = 0
        for row in range(rows):
            maxValue += values[row][0]
        return maxValue

    maxValues = [[0] * cols] * rows

    for i in range(rows):
        for j in range(cols):
            left = 0
            up = 0
            if i > 0:  # i=0 边界
                up = maxValues[i - 1][j]
            if j > 0:
                left = maxValues[i][j - 1]
            maxValues[i][j] = max(left, up) + values[i][j]
    maxValue = maxValues[rows - 1][cols - 1]
    return maxValue


  #########优化#############
# 只用一个一维数组来代替二维数组maxValues
# 该数组前面j个数字分别是当前i行前面j个格子礼物的最大价值
# 之后的数字分别保存i-1行,n-j个格子的礼物的最大价值

def getMaxValue_solution2(values):
    if not values:
        return 0
    rows = len(values)
    if not isinstance(values[0], list):
        maxValue = sum(values)
        return maxValue
    else:
        cols = len(values[0])
    if cols == 1:
        maxValue = 0
        for row in range(rows):
            maxValue += values[row][0]
        return maxValue

    maxValues = [0] * cols

    for i in range(rows):
        for j in range(cols):
            left = 0
            up = 0
            if i > 0:  # i=0 边界
                up = maxValues[j]
            if j > 0:
                left = maxValues[j - 1]
            maxValues[j] = max(left, up) + values[i][j]
    maxValue = maxValues[cols - 1]
    return maxValue

测试

################测试1#################
#功能测试
# 功能测试
# 多行多列的矩阵
values = [[1, 10, 3, 8], [12, 2, 9, 6], [5, 7, 4, 11], [3, 7, 16, 5]]
getMaxValue_solution1(values)

# 一行或一列矩阵
values = [1, 10, 3, 8]  # 一行
getMaxValue_solution1(values)

values = [[1], [10], [3], [8]]  # 一列
getMaxValue_solution1(values)

# 只有一个数字的矩阵
values = [1]
getMaxValue_solution1(values)

# 特殊输入测试
getMaxValue_solution1(None)


##############优化后测试##########
# 功能测试
# 多行多列的矩阵
values = [[1, 10, 3, 8], [12, 2, 9, 6], [5, 7, 4, 11], [3, 7, 16, 5]]
getMaxValue_solution2(values)

# 一行或一列矩阵
values = [1, 10, 3, 8]  # 一行
getMaxValue_solution2(values)

values = [[1], [10], [3], [8]]  # 一列
getMaxValue_solution2(values)

# 只有一个数字的矩阵
values = [1]
getMaxValue_solution2(values)

# 特殊输入测试
getMaxValue_solution2(None)


面试题48:最长不含重复字符的子字符串

题目:最长不含重复字符的子字符串

​ 请从字符串中找出一个最长的不包含重复字符的子字符串,计算最长该子字符串的长度.假设字符串中只包含’a’ ~ ‘z’ 的字符

`输入: 字符串’arabcacfr’

输出:最长的不包含重复字符的子字符串是'acfr'

思路

动态规划

f(i) f ( i ) :以第i个字符为结尾的不包含重复字符的子字符串的最长长度

(1) 第i个字符之前没出现过, f(i)=f(i1)+1 f ( i ) = f ( i − 1 ) + 1

(2) 第i个字符之前已经出现过。

​ 计算第i个字符和它上次出现在字符串中的位置的距离,d

​ 1、 d<=f(i1) d <= f ( i − 1 ) 第i个字符上次出现在f(i-1)对应的最长子字符串之中

f(i)=d f ( i ) = d

​ 2、 d>f(i1) d > f ( i − 1 ) 第i个字符上次出现在f(i-1)对应的最长子字符串之前

f(i)=f(i1)+1 f ( i ) = f ( i − 1 ) + 1

代码

#################面试题48#######################
#最长不含重复字符的子字符串

def longestSubstringWithoutDuplication(string):
    curLength = 0
    maxLength = 0
    position = [-1] * 26  # 26个字母
    if not string:
        return None
    for i in range(len(string)):
        preIndex = position[ord(string[i]) - ord('a')]
        if preIndex < 0 or i - preIndex > curLength:
            curLength += 1
        else:
            if curLength > maxLength:
                maxLength = curLength
            curLength = i - preIndex
        position[ord(string[i]) - ord('a')] = i

    if curLength > maxLength:
        maxLength = curLength

    return maxLength

测试

################测试1#################
# 功能测试
# 包含多个字符的字符串
longestSubstringWithoutDuplication('arabcacfr')

# 只有一个字符的字符串
longestSubstringWithoutDuplication('a')

# 所有字符都相同的字符串
longestSubstringWithoutDuplication('aaaa')

# 特殊输入测试
longestSubstringWithoutDuplication(None)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值