题目来源:力扣(LeetCode)和传说
链接:https://leetcode-cn.com/problems
特别鸣谢:来自夸夸群的 醉笑陪公看落花@知乎,王不懂不懂@知乎,QFIUNE@csdn
感谢小伙伴们督促学习,一起进步
给你一个整数数组 nums ,返回 nums 中所有 等差子序列 的数目。
如果一个序列中 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该序列为等差序列。
例如,[1, 3, 5, 7, 9]、[7, 7, 7, 7] 和 [3, -1, -5, -9] 都是等差序列。
再例如,[1, 1, 2, 5, 7] 不是等差序列。
数组中的子序列是从数组中删除一些元素(也可能不删除)得到的一个序列。
例如,[2,5,10] 是 [1,2,1,2,4,1,5,10] 的一个子序列。
题目数据保证答案是一个 32-bit 整数。
示例 1:
输入:nums = [2,4,6,8,10]
输出:7
解释:所有的等差子序列为:
[2,4,6]
[4,6,8]
[6,8,10]
[2,4,6,8]
[4,6,8,10]
[2,4,6,8,10]
[2,6,10]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence
示意图如下:
动态转移数组 f[j][i] 表示以 nums[i] 结尾的动态数组个数+1
解题代码
class Solution:
def numberOfArithmeticSlices(self, nums):
def solve3(nums):
f = [defaultdict(int) for _ in nums]
ans = 0
for i in range(len(nums)):
for j in range(i):
d = nums[i]-nums[j]
ans += f[j][d]
f[i][d] += f[j][d]+1
return ans
return solve3(nums)
先用交换的思想求子集 O(n!+(n-1)!+(n-2)!+… + 2! + 1),再判断子集是否是等差数列 O(n)
整体时间复杂度 O((n!+(n-1)!+(n-2)!+… + 2! + 1) * n)
优化
优化之后的时间复杂度 O((2^n)-1)
参考 leetcode 46 和47 . 全排列,两种生成树的方案来解决全排列问题
'''
超时 O((2^n)-1) * O(n)
'''
class Solution:
def numberOfArithmeticSlices(self, nums):
self.count = 0
memor = set()
def solve1(nums):
nums.sort()
dnums = [(v,i) for i,v in enumerate(nums)]
DFS(dnums,0)
def DFS(dnums,i):
if i == len(dnums):return
for j in range(i,len(nums)):
if dnums[i][1] > dnums[j][1] or (i>0 and dnums[i-1][1]>dnums[j][1]):
continue
dnums[i],dnums[j] = dnums[j],dnums[i]
if i>=2 and tuple(dnums[:i+1]) not in memor and check(dnums,i):
self.count += 1
memor.add(tuple(dnums[:i+1]))
DFS(dnums,i+1)
dnums[i],dnums[j] = dnums[j],dnums[i]
def check(dnums,i):
for j in range(1,i):
if dnums[j+1][0]-dnums[j][0] != dnums[j][0]-dnums[j-1][0]:
return False
return True
solve1(nums)
return self.count
'''
优化等差数列判断 - 超时
超时 O((2^n)-1) * O(1)
'''
class Solution:
def numberOfArithmeticSlices(self, nums):
self.count = 0
memor = set()
def solve1(nums):
nums.sort()
dnums = [(v,i) for i,v in enumerate(nums)]
DFS(dnums,0,False)
def DFS(dnums,i,dc):
if i == len(dnums):return
for j in range(i,len(nums)):
if dnums[i][1] > dnums[j][1] or (i>0 and dnums[i-1][1]>dnums[j][1]):
continue
dnums[i],dnums[j] = dnums[j],dnums[i]
dc = check(dnums,i,dc)
if i>=2 and tuple(dnums[:i+1]) not in memor and dc:
self.count += 1
memor.add(tuple(dnums[:i+1]))
DFS(dnums,i+1,dc)
dnums[i],dnums[j] = dnums[j],dnums[i]
def check(dnums,i,dc):
if not dc and i>2:return False
return dnums[i][0]-dnums[i-1][0] == dnums[i-1][0]-dnums[i-2][0]
solve1(nums)
return self.count
todo