Program to count non-empty subsets where sum of min and max element of set is less than k in Python

Given a list of numbers and a value k, we need to find the number of non-empty subsets where the sum of minimum and maximum elements is less than or equal to k. Note that subsets are treated as multisets, meaning duplicate values can appear since they refer to specific positions in the list.

For example, if nums = [2, 2, 5, 6] and k = 7, the valid subsets are: [2], [2], [2, 2], [2, 5], [2, 5], [2, 2, 5], giving us 6 subsets total.

Algorithm

The approach uses a two-pointer technique after sorting the array ?

  • Sort the array to easily find min and max elements
  • Use two pointers: left (i) for minimum, right (j) for maximum
  • For each valid range [i, j], count subsets using 2^(j-i)
  • Move pointers to explore all possibilities

Implementation

def count_valid_subsets(nums, k):
    n = len(nums)
    nums.sort()
    ans = 0
    j = n - 1
    
    for i in range(n):
        # Move right pointer left while sum exceeds k
        while j >= 0 and nums[i] + nums[j] > k:
            j -= 1
        
        # If valid range exists, count subsets
        if i <= j and nums[i] + nums[j] <= k:
            ans += 1 << (j - i)  # Same as 2^(j-i)
    
    return ans

# Test with example
nums = [2, 2, 5, 6]
k = 7
result = count_valid_subsets(nums, k)
print(f"Number of valid subsets: {result}")
Number of valid subsets: 6

How It Works

Let's trace through the example with nums = [2, 2, 5, 6] and k = 7 ?

def count_valid_subsets_with_trace(nums, k):
    n = len(nums)
    nums.sort()
    print(f"Sorted array: {nums}")
    ans = 0
    j = n - 1
    
    for i in range(n):
        # Move right pointer left while sum exceeds k
        while j >= 0 and nums[i] + nums[j] > k:
            j -= 1
        
        if i <= j and nums[i] + nums[j] <= k:
            subsets_count = 1 << (j - i)
            print(f"i={i}, j={j}, nums[i]={nums[i]}, nums[j]={nums[j]}, subsets: {subsets_count}")
            ans += subsets_count
    
    return ans

nums = [2, 2, 5, 6]
k = 7
result = count_valid_subsets_with_trace(nums, k)
print(f"Total valid subsets: {result}")
Sorted array: [2, 2, 5, 6]
i=0, j=2, nums[i]=2, nums[j]=5, subsets: 4
i=1, j=2, nums[j]=2, nums[j]=5, subsets: 2
Total valid subsets: 6

Key Points

  • Sorting: Ensures min element is at position i and max at position j
  • Two pointers: Efficiently finds valid ranges without checking all combinations
  • Power of 2: For range [i, j], there are 2^(j-i) possible subsets
  • Bit shifting: 1 << n is equivalent to 2^n but faster

Alternative Implementation

def count_subsets_alternative(nums, k):
    nums.sort()
    count = 0
    
    for i in range(len(nums)):
        for j in range(i, len(nums)):
            if nums[i] + nums[j] <= k:
                # All subsets between i and j are valid
                count += 2 ** (j - i)
            else:
                break  # No need to check further as array is sorted
    
    return count

# Test
nums = [2, 2, 5, 6]
k = 7
print(f"Alternative method result: {count_subsets_alternative(nums, k)}")
Alternative method result: 6

Conclusion

The two-pointer approach efficiently counts valid subsets by leveraging the sorted array property. The key insight is that for any valid range [i, j], we can form 2^(j-i) subsets where the minimum is nums[i] and maximum is nums[j].

Updated on: 2026-03-25T11:27:40+05:30

322 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements