↓快轉到主要內容
  1. LeetCode/

LeetCode 1498: Number of Subsequences That Satisfy the Given Sum Condition

·2 分鐘· ·
LeetCode Medium Two-Pointers Sorting Binary-Search Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: medium 第一次嘗試:2026-01-24

  • 提交紀錄:Accepted ×2 → Wrong Answer → Accepted ×2

解題思路
#

子序列是否合法只看最小值 + 最大值,跟元素的原本順序無關,所以可以先排序。

排序後用對撞指針:

  • nums[left] + nums[right] > target:nums[right] 跟目前最小的都配不起來,跟更大的更不可能,丟掉它,right -= 1。
  • 否則,以 nums[left] 當最小值:一定要選 nums[left],left + 1..right 這 right - left 個元素可選可不選,最大值一定 <= nums[right],共 2^(right - left) 種。加完 left += 1。

2 的次方要取模,用 pow(2, e, MOD),或先預處理次方表。

我的嘗試
#

第一次 AC 之後我自己重寫了幾次。中間有一版 WA:把判斷改成 while ... else,內層 while 沒有加 left <= right,right 會一路減到 left 左邊。這時 right - left 是負的,而 Python 的 pow(2, -1, MOD) 不會報錯,會回傳 2 的模反元素 500000004,答案就被加進一個奇怪的大數。

例如 nums = [3, 5, 6, 7]、target = 9:答案是 4,這版回傳 500000008。

內層 while 加上 left <= right 後 AC。

正確解法
#

class Solution:
    def numSubseq(self, nums: List[int], target: int) -> int:
        MOD = 10 ** 9 + 7
        nums.sort()
        left, right = 0, len(nums) - 1
        ans = 0
        while left <= right:
            if nums[left] + nums[right] > target:
                right -= 1                         # nums[right] 沒有可以配的最小值
            else:
                ans = (ans + pow(2, right - left, MOD)) % MOD
                left += 1                          # 以 nums[left] 為最小值的都算完了
        return ans

複雜度
#

時間 O(n log n)(每次 pow 是 O(log n),預處理次方表可以變成 O(1)),空間 O(1)(不算排序)。

要特別避免的錯誤
#

  • 以為子序列要保持順序就不能排序:這題只看最小值和最大值。
  • right 跑到 left 左邊:Python 的 pow 負指數加模數不會報錯,會默默算錯。
  • 2^(right - left) 不是 2^(right - left + 1):最小值 nums[left] 一定要選。

面試口說整理
#

合法與否只看最小值加最大值,所以先排序。對撞指針:兩端加起來太大,就把右端丟掉;夠小的話,以左端當最小值,它一定要選,中間 right - left 個任意選,共 2^(right - left) 種,加完左端前進。時間 O(n log n)。

相關文章

LeetCode 825: Friends Of Appropriate Ages
·2 分鐘
LeetCode Medium Two-Pointers Sorting Binary-Search Array
LeetCode 825 解題筆記:排序後,每個人能送出邀請的對象是年齡落在 (0.5 × age + 7, age] 的一段區間,用兩個同向指針維護區間再扣掉自己
LeetCode 923: 3Sum With Multiplicity
·3 分鐘
LeetCode Medium Two-Pointers Sorting Hash-Table Counting Array
LeetCode 923 解題筆記:排序後固定第一個數、對撞指針找另外兩個;兩端值相同時用組合數一次算完,不同時把兩端各自的重複數相乘
LeetCode 948: Bag of Tokens
·1 分鐘
LeetCode Medium Two-Pointers Greedy Sorting Array
LeetCode 948 解題筆記:排序後,用最小的 token 換分數、用最大的 token 換能量;只有分數 > 0 才能換能量,換不了就停
LeetCode 3413: Maximum Coins From K Consecutive Bags
·2 分鐘
LeetCode Medium Sliding-Window Greedy Sorting Prefix-Sum Binary-Search Array
LeetCode 3413 解題筆記:最佳的 k 個袋子,一定有一端對齊某段的端點;分別算「左端對齊段的起點」和「右端對齊段的終點」(鏡像後重用同一個函式)
LeetCode 2779: Maximum Beauty of an Array After Applying Operation
·1 分鐘
LeetCode Medium Sliding-Window Sorting Binary-Search Array
LeetCode 2779 解題筆記:每個數可以變成 [x - k, x + k] 裡的任何值,一群數能變成同一個值 ⇔ 最大 - 最小 <= 2k;排序後找最長的這種視窗
LeetCode 611: Valid Triangle Number
·1 分鐘
LeetCode Medium Array Two-Pointers Binary-Search Greedy
LeetCode 611 解題筆記:排序後固定最長邊 k,左右指針找兩短邊:和夠大時中間的都可以,一次加 j - i 個