小试牛刀
题目:给定一个数组,判断是否存在子集之和为100
- 递归解法
# param:arr为数组, i为数组长度-1, target为目标数(100)
def recur_subset(arr, i, target):
if arr[i] == target:
return True
if i == 0:
return arr[0] == target
if arr[i] > target:
return dp_recur(arr, i-1, target)
else:
A = dp_recur(arr, i-1, target-arr[i])
B = dp_recur(arr, i-1, target)
return A or B
- 动态规划
import numpy as np
# params: arr为给定数组, target为目标数(100)
def dp_subset(arr, target):
length = len(arr)
# 纵向为arr的元素索引, 横向为target
dp = np.zeros((len(arr), target+1))
# 当到达arr[0]时, 将与arr[0]不相等的置为False, 相等的置为True
dp[0, :] = False
# 当target为0时,返回True, 即二维dp第一列为True
dp[:, 0] = True
# 判断界限, 如果arr[0]>target则越界
if arr[0] < target:
dp[0, arr[0]] = True
for i in range(1, len(arr)):
for j in range(1, target+1):
if arr[i] > j:
dp[i, j] = dp[i-1, j]
else:
A = dp[i-1, j-arr[i]]
B = dp[i-1, j]
dp[i, j] = A or B
print(dp)
return dp[-1, -1]
leetcode 5. 最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解(动态规划):
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
if len(s) <= 1:
return s
length = len(s)
# 创建dp二维列表
dp = [[False for _ in range(length)] for _ in range(length)]
max_length = 1
res = s[0]
for r in range(1, length):
for l in range(r):
# 若首s[l]尾s[r]相等, 且中间的子串也是回文串 或者 子长度小于等于1, 则此为回文串
if s[l] == s[r] and (r-l <= 2 or d[l+1][r-1]):
dp[l][r] = True
cur_length = r - l + 1
if cur_length > max_length:
max_length = cur_length
res = s[l:r+1]
return res
leetcode 53. 最大子序列和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
res = nums[0]
max_sum = 0
for i in nums:
if max_sum > 0:
max_sum += i
else:
max_sum = i
res = max(res, max_sum)
return res
leetcode 62. 不同路径Ⅰ
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
例如,上图是一个7 x 3 的网格。有多少可能的路径?
说明:m 和 n 的值均不超过 100。
示例 1:
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
- 向右 -> 向右 -> 向下
- 向右 -> 向下 -> 向右
- 向下 -> 向右 -> 向右
示例 2:
输入: m = 7, n = 3
输出: 28
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution(object):
def uniquePaths(self, m, n):
"""
:type m: int
:type n: int
:rtype: int
"""
if m == 1 or n == 1:
return 1
dp = [[0 for _ in range(m)] for _ in range(n)]
for i in range(n):
for j in range(m):
if i == 0:
dp[i][j] = 1
if j == 0:
dp[i][j] = 1
else:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
# print(dp)
return dp[-1][-1]
leetcode 63. 不同路径Ⅱ
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
说明:m 和 n 的值均不超过 100。
示例 1:
输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
- 向右 -> 向右 -> 向下 -> 向下
- 向下 -> 向下 -> 向右 -> 向右
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution(object):
def uniquePathsWithObstacles(self, obstacleGrid):
"""
:type obstacleGrid: List[List[int]]
:rtype: int
"""
row = len(obstacleGrid)
col = len(obstacleGrid[0])
dp = [[0 for _ in range(col)] for _ in range(row)]
for i in range(row):
for j in range(col):
if obstacleGrid[i][j] == 1:
dp[i][j] = 0
continue
if i == 0 and j == 0:
if obstacleGrid[i][j] == 1:
return 0
else:
dp[i][j] = 1
elif i == 0 and j >= 1:
print('xbb')
dp[i][j] = dp[i][j-1]
elif j == 0 and i >= 1:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = dp[i][j-1] + dp[i-1][j]
return dp[-1][-1]
leetcode 120. 三角形最小路径和
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/triangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution(object):
def minimumTotal(self, triangle):
"""
:type triangle: List[List[int]]
:rtype: int
"""
if len(triangle) == 0:
return 0
# 从倒数第二行依次遍历每一行
row = len(triangle) - 2
for i in range(row, -1, -1):
for j in range(len(triangle[i])):
# 取下一行相邻得两个数中较小的与之相加
triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1])
return triangle[0][0]
leetcode 121. 买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路一
class Solution(object):
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
buy = prices[0]
profit = [0 for _ in range(len(prices))]
for i in range(len(prices)):
if prices[i] > buy:
profit[i] = prices[i] - buy
else:
buy = prices[i]
return max(profit)
思路二
class Solution_1(object):
def maxProfit(self, prices):
min_price = prices[0]
max_profit = 0
for i in range(len(prices)):
min_price = min(min_price, prices[i])
max_profit = max(max_profit, prices[i] - min_price)
return max_profit
leetcode 122. 买卖股票的最佳时机 II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
算法一:峰谷法
假设给定的数组为:
[7, 1, 5, 3, 6, 4]
如果我们在图表上绘制给定数组中的数字,我们将会得到:
如果我们分析图表,那么我们的兴趣点是连续的峰和谷。
用数学语言描述为:
关键是我们需要考虑到紧跟谷的每一个峰值以最大化利润。如果我们试图跳过其中一个峰值来获取更多利润,那么我们最终将失去其中一笔交易中获得的利润,从而导致总利润的降低。
例如,在上述情况下,如果我们跳过 peak_i 和 valley_j 试图通过考虑差异较大的点以获取更多的利润,获得的净利润总是会小与包含它们而获得的静利润,因为 C 总是小于 A+B。
作者:LeetCode
链接:https://leetcode-cn.com/problems/two-sum/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution(object):
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if len(prices) < 2:
return 0
profit = 0
peek = prices[0]
valley = prices[0]
i = 0
while i < len(prices)-1:
while i < len(prices)-1 and prices[i] >= prices[i+1]:
i += 1
valley = prices[i]
while i < len(prices)-1 and prices[i] <= prices[i+1]:
i += 1
peek = prices[i]
profit += peek - valley
return profit
算法二:简单的一次遍历
[1, 7, 2, 3, 6, 7, 6, 7]
与此数组对应的图形是:
从上图中,我们可以观察到 A+B+C 的和等于差值 D 所对应的连续峰和谷的高度之差。
作者:LeetCode
链接:https://leetcode-cn.com/problems/two-sum/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution(object):
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if len(prices) < 2:
return 0
profit = 0
for i in range(len(prices)-1):
if prices[i+1] > prices[i]:
profit += prices[i+1] - prices[i]
return profit