python 力扣 完全平方数、组合总和、加油站

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]))

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

剁椒排骨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值