题目
注意:
- 题目是计算子序列的数目
这里要明确一个概念,子序列是原序列中的可非连续的元素列,假设有个数列[1,2,3,4,5,6]则[1,2,3],[1,5,6]都是原数列的子数列 - 程序输入的数列nums是无序的,可以先对nums进行排序再操作,对结果没有什么影响,但是可以简化程序代码
【代码】双指针
执行用时:7380 ms, 在所有 Python3 提交中击败了27.50% 的用户
内存消耗:24.6 MB, 在所有 Python3 提交中击败了50.00% 的用户
通过测试用例:62 / 62
class Solution:
def numSubseq(self, nums: List[int], target: int) -> int:
nums.sort()
left,right=0,len(nums)-1
ans=0
while left<=right:
if nums[left]+nums[right]<=target:
ans+=2**(right-left)
left+=1
else:
right-=1
return ans%(1000000007)
【方法2】二分法
执行用时:7992 ms, 在所有 Python3 提交中击败了14.17% 的用户
内存消耗:24.9 MB, 在所有 Python3 提交中击败了5.83% 的用户
通过测试用例:62 / 62
class Solution:
def numSubseq(self, nums: List[int], target: int) -> int:
n = len(nums)
P = 10**9 + 7
nums.sort()
ans = 0
for i, num in enumerate(nums):
if nums[i] * 2 > target:
break
maxValue = target - nums[i]
pos=-1
left,right=i,n-1
while left<=right:
mid=left+(right-left)//2
if nums[mid]<=(target-num):
pos=mid
left=mid+1
else:
right=mid-1
contribute = 2**(pos - i) if pos >= i else 0
ans += contribute
return ans % P
【方法2的加速版本】
执行用时:580 ms, 在所有 Python3 提交中击败了58.33% 的用户
内存消耗:24.5 MB, 在所有 Python3 提交中击败了69.17% 的用户
通过测试用例:62 / 62
class Solution:
def numSubseq(self, nums: List[int], target: int) -> int:
n = len(nums)
P = 10**9 + 7
nums.sort()
ans = 0
f = [1] + [0] * (n - 1)
for i in range(1, n):
f[i] = f[i - 1] * 2 % P
for i, num in enumerate(nums):
if nums[i] * 2 > target:
break
maxValue = target - nums[i]
pos=-1
left,right=i,n-1
while left<=right:
mid=left+(right-left)//2
if nums[mid]<=(target-num):
pos=mid
left=mid+1
else:
right=mid-1
contribute = f[pos - i] if pos >= i else 0
ans += contribute
return ans % P
【方法3】二分
执行用时:220 ms, 在所有 Python3 提交中击败了95.83% 的用户
内存消耗:24.5 MB, 在所有 Python3 提交中击败了70.83% 的用户
通过测试用例:62 / 62
class Solution:
def numSubseq(self, nums: List[int], target: int) -> int:
n = len(nums)
P = 10**9 + 7
f = [1] + [0] * (n - 1)
# print(f)
for i in range(1, n):
f[i] = f[i - 1] * 2 % P
# print(f)
nums.sort()
ans = 0
for i, num in enumerate(nums):
if nums[i] * 2 > target:
break
maxValue = target - nums[i]
pos = bisect.bisect_right(nums, maxValue) - 1
# print("maxValue:",maxValue," pos:",pos,' i:',i)
contribute = f[pos - i] if pos >= i else 0
# print(contribute)
ans += contribute
return ans % P