1. 829. 连续整数求和
给定一个正整数 N
,试求有多少组连续正整数满足所有数字之和为 N
?
示例 1:
输入: 5
输出: 2
解释: 5 = 5 = 2 + 3,共有两组连续整数([5],[2,3])求和后为 5。
示例 2:
输入: 9
输出: 3
解释: 9 = 9 = 4 + 5 = 2 + 3 + 4
示例 3:
输入: 15
输出: 4
解释: 15 = 15 = 8 + 7 = 4 + 5 + 6 = 1 + 2 + 3 + 4 + 5
解法1: 暴力 超时 😣
class Solution:
def consecutiveNumbersSum(self, N: int) -> int:
count = 1 # 等于1: 最后一个N的情况;
end = (N+1)//2
for i in range(1, end): # 这种方法可行,但超时, 怎么优化
sum_add = 0
test = []
for j in range(i, N+1):
sum_add = sum_add + j
if sum_add == N:
count += 1
break
elif sum_add > N:
break
return count
解法2: 变成了数学题求解, 难受😭
假设连续q到p相加等于N, 则满足:
推出:
设, , 则为2N的因子(因子:a*b=2N),则有:
由为奇数,可以为奇数,则a,b必须一个为奇数一个为偶数,则转变为 求a,b是2N 的因子,而且是一奇一偶数【写代码的点】;
其中, a小,可以推出, 若,则;
若要求出p,q则公式为: , ;
class Solution:
def consecutiveNumbersSum(self, N: int) -> int:
# a,b必是一奇一偶
import math
a = 1
res = 0
end = int(math.sqrt(2*N))
while a <= end:
if 2*N % a == 0: # i是2N的因子
b = 2*N // a
if a%2 + b%2 == 1: # a,b是一奇一偶数
# q = (a+b-1)//2
# p = (b-a+1) // 2
# print(p, q) # 找到的 连续数组开始 结尾的数
res += 1
a = a + 1
return res
参考:此处
解法3: 大神思路;
class Solution:
def consecutiveNumbersSum(self, N: int) -> int:
# 解题思路:
# 当1个数时, 必然有一个N
# 当2个数时,x,x+1相加等于N, 则(N-1)//2 ==0,则必存在解;
# 当3个数时,x,x+1,x+2相加等于N,则(N-2-1)//3==0,则必存在解;
# 当4个数时,x,x+1,x+2,x+3相加等于N, 则(N-3-2-1)==0,必存在解;
i = 1
res = 0
while N > 0: # 判断条件设置的 极为精妙;
if N % i == 0:
res += 1
N = N - i #
i = i + 1
return res
2. 整数分解
给定一个正整数n,一个正整数k,一个可行的数字组合是一组正整数,它们的和为n,且组合中数字个数小于等于k,组合中允许数字重复出现 输出:所有可能的组合数(两个组合中出现的数字相同,顺序不同计为同一个); 此题和连续整数求和相比是 去掉了 连续 这个条件;
解法1: ??
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2:
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明: 你可以假设 n 不小于 2 且不大于 58。
解法1: 动态规划dp; 动态规划推导公式:
if n <= 3: #
return 1*(n-1)
dp = [0]*(n+1) # dp[i]表示i拆分成至少两个整数的和,这些整数的乘积最大值
dp[2:n+1] = list(range(2, n+1)) # 初始化为 原始值;
# 递归公式i拆分成j和i-j, dp[i]=dp[j]*dp[i-j]
for i in range(4, n + 1):
for j in range(i): # 求dp[i]遍历完i之前所有值
dp[i] = max(dp[i], dp[j] * dp[i - j]) # 动态规划 总有这个条件;
return dp[n]
解法2: 动态规划dp; 动态规划还是不好理解, 需要对题目进行记忆,
对于的正整数 n,当时,可以拆分成至少两个正整数的和。令 k 是拆分出的第一个正整数,则剩下的部分是 , 可以不继续拆分,或者继续拆分成至少两个正整数的和。
创建数组,其中 表示将正整数拆分成至少两个正整数的和之后,这些正整数的最大乘积。特别地,0不是正整数,1是最小的正整数,0 和 1 都不能拆分,因此。
class Solution:
def integerBreak(self, n: int) -> int:
# 1. 动态规划方法一
dp = [0]*(n+1) # 0,1不能拆分,dp[0]=0, dp[1]=0
for i in range(2, n+1):
for j in range(i): # 求出dp[i] # 最大值;
dp[i] = max(dp[i], j * (i-j), j*dp[i-j])
return dp[n]
4. 397. 整数替换
给定一个正整数 n ,你可以做如下操作:
如果 n 是偶数,则用 n / 2替换 n 。
如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。
n 变为 1 所需的最小替换次数是多少?
示例 1:
输入:n = 8
输出:3
解释:8 -> 4 -> 2 -> 1
示例 2:
输入:n = 7
输出:4
解释:7 -> 8 -> 4 -> 2 -> 1
或 7 -> 6 -> 3 -> 2 -> 1
示例 3:
输入:n = 4
输出:2
提示:
1 <= n <= 231 - 1
解法1: 好不容尝试dp, 超内存,超时间, n太大,不该使用dp;
class Solution:
def integerReplacement(self, n: int) -> int:
# n非常大,存在超时的问题
if n == 1:
return 0
if n == 2:
return 1
dp = [0]*(n+1) # dp[1]=0, dp[2]=1
dp[1] = 0
dp[2] = 1
for i in range(3, n+1):
if i %2 == 0:
dp[i] = dp[i//2] + 1
else:
dp[i] = min(dp[(i+1)//2]+1, dp[(i-1)//2]+1) + 1
return dp[n]
解法2: 递归
class Solution:
def integerReplacement(self, n: int) -> int:
# 纯递归; 看到题 应该超那个思路想(1.dp, 2.递归,3.贪心)还是不会; 被当时最熟悉的思路(之前做过的题影响)
if n <= 1:
return 0
if n <= 2:
return 1
if n % 2 == 0: # 偶数
return self.integerReplacement(n//2) + 1
else:
return min(self.integerReplacement(n+1), self.integerReplacement(n-1)) + 1
6. 39. 组合总和
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
解法1: 递归 +回溯+ 去重复
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
# 递归
result = []
def digui(target, target_list):
for item in candidates:
if target - item == 0: # 可以相等记录下来
tem = target_list+[item]
if sorted(tem) not in result: # 去重复
result.append(sorted(tem))
elif target - item > 0:
digui(target-item, target_list+[item]) # 传参时, 不要加进去
else:
pass
digui(target, [])
# temp = []
# for item in result: # 去重复的问题 用sorted
# if sorted(item) not in temp:
# temp.append(sorted(item))
return result