python1:完全平方数
完全平方数 题目: 给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
输入:12 输出:3
思路:
动态规划
完全背包问题,对于本题就是有一个一定容量的背包,然后有一个集合,这个集合里有各种重量的物品,把这些物品放进背包中,使得背包到达它的容量,并且背包里放的物品数量最少。
背包容量就是n,各种重量的物品就是平方数,这些平方数肯定要小于或者等于背包容量,不然也不能往里放。
- 先建立一个数组,里面放着背包里可以放的物品。
- 建立一个长度为n+1的动态数组,其中dp[i]表示和为i的完全平方数的最少数量。初始化里面是最大数量,题目中说最大容量是10的四次方,可选择的最小重量是1,所以最多数量就是10的四次方。
- 定义dp[0] = 0,要找的是dp[n]的最小数,怎么找呢,我们对于背包里面可以放的物品,从小到大依次往里放,首先对于1这个数,遍历动态数组,肯定要从索引等于1的位置开始,因为索引小于1的位置,也就是背包容量小于1的话,根本放不进,这一趟是只能往里放1的情况下的物品数量,然后遍历下一个物品4,从索引4开始更新物品数量,取最小的物品数量,直到遍历完可放的全部数,最后返回dp[n],即和为n的完全平方数的最小数量。
class Solution(object):
def numSquares(self, n):
nums = [i ** 2 for i in range(1, int(n ** 0.5) + 1)]
dp = [10 ** 4] * (n + 1)
dp[0] = 0
for num in nums:
for j in range(num, n + 1):
dp[j] = min(dp[j], dp[j - num] + 1)
return dp[n]
if __name__ == '__main__':
s = Solution()
print(s.numSquares(12))
python2:组合总和
组合总和 题目:给定一个无重复元素的数组nums和一个目标整数 target ,找出 nums中可以使数字和为 target 的所有不同组合。
nums中的同一个数字可以无限制重复被选取 。 输入:nums = [2,3,6,7], target = 7 输出:[[2,2,3],[7]]
题解一:
1.res保存最终解,path记录当前组合,sum记录当前path数字之和。
2.在dfs函数中,如果当前sum与target相等,则说明找到一个结果,将path加入res(需要判断res中是否已经存在和path相同的组合)。
如果当前sum小于target则从candidates中选择candidates[i]加入path,同时更新sum,然后再次调用dfs函数。
class Solution(object):
def combinationSum(self, candidates, target):
res = []
path = []
n = len(candidates)
sum = 0
def dfs(candidates, target, path, res, sum):
for i in range(n):
if sum == target:
newpath = sorted(path[:])
if newpath not in res:
res.append(newpath)
return
if sum < target:
path.append(candidates[i])
sum = sum + candidates[i]
dfs(candidates, target, path, res, sum)
path.pop()
sum = sum - candidates[i]
dfs(candidates, target, path, res, sum)
return res
if __name__ == '__main__':
s = Solution()
print(s.combinationSum([2,3,6,7], 7))
python3:加油站
加油站 在一条环路上有N个加油站,其中第i个加油站有汽油gas[i]升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1个加油站需要消耗汽油cost[i]升。 你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
说明:
如果题目有解,该答案即为唯一答案。 输入数组均为非空数组,且长度相同。 输入数组中的元素均为非负数。
输入: gas = [1,2,3,4,5] cost = [3,4,5,1,2]
输出: 3
class Solution(object):
def canCompleteCircuit(self, gas, cost):
"""
分析:
第i个加油站有gas[i]升汽油,从第i个加油站开往第i+1个加油站需要消耗汽油cost[i]升,从这里可以看出,行驶方向只能正序0->1->2这种
油箱容量无限,从其中一个加油站出发,初始油箱为空
目标:绕环路一圈,则返回出发加油站编号,否则返回-1 (如果有解则解唯一)
思路:
1. 用gas对应位去减去cost得到一个subtraction
2. subtraction的总和大于等于0的话,则一定是有解的
3. 如果有解的话,subtraction为负值的地方,则表示不能作为初始的位置, 所有非负的地方都可以作为候选起始位置,这个时候要要根据subtraction来判断那个位置作为初始位置(唯一)
4. 依次判断上面非负位置
5. 可能会出现几种结束条件
i) i=0 j=4 总和满足大于等于0的合法情况
ii) i=3 j=2 总和满足大于等于0的合法情况
iii) 总和小于0的非法情况
:type gas: List[int]
:type cost: List[int]
:rtype: int
"""
subtraction = list(map(lambda x: x[0] - x[1], zip(gas, cost))) # 进行数组对应位相减
for i in range(len(subtraction)):
if subtraction[i] < 0:
continue
j = i
curSum = 0
while True:
curSum += subtraction[j]
# i=4 j=3这种情况的结束条件
if j == i - 1:
break
# j=4 i=0这种情况的结束条件
if j - i + 1 == len(subtraction):
break
if curSum < 0:
break
if j < len(subtraction) - 1:
j += 1
else:
j = 0
# 符合的判决条件
if (j == i - 1 or j - i + 1 == len(subtraction)) and curSum >= 0:
return i
return -1
if __name__ == '__main__':
s = Solution()
print(s.canCompleteCircuit([1,2,3,4,5], [3,4,5,1,2]))