Preface
I asked a question before where I was looking to understand the complexity class of the following problem:
Given a range of integers $\{a,a+1,...,b-1,b\}$, find a subset of size $k$ such that the sum is equal to $s$.
I had found a $O(k)$ algorithm as hinted at by the accepted answer. After playing around with the results of this algorithm, I found that it was not 100% what I was looking for.
Problem
Given a range of integers $\{a,a+1,...,b-1,b\}$, find the range of the $i^{th}$ element of all subsets of size $k$, sorted in increasing order, that sum to $s$:
For example, given $k = 3$, $a = 1$, $b = 8$, and $s = 11$ we get the following list of all possible solutions sorted in increasing order:
{ 1 | 2 | 8 }
{ 1 | 3 | 7 }
{ 1 | 4 | 6 }
{ 2 | 3 | 6 }
{ 2 | 4 | 5 }
By grouping each column, we can see the ranges of values for each of the $i^{th}$ elements in the set:
- $\{1,2\}$
- $\{2,3,4\}$
- $\{5,6,7,8\}$
Question
I would like an algorithm that in constant time could generate the range of values for a $i^{th}$ element for all subsets summing to $s$ for a given $a$ and $b$.
get_ith_range(int k, int a, int b, int s, int i)
int lower_bound, upper_bound
// Some cool O(1) algorithm...
return (lower_bound, upper_bound)
I do not mind if it is not $O(1)$, but I feel as though there should be a way to get there at least in $O(k)$.
Attempts
Currently, I have a way to generate the smallest for the $1^{st}$ range and the largest for the $k^{th}$ range (not in constant time though). But, I have not been able to even get to where I could generate the full $i^{th}$ range in any case.
Using my solution from my previous question, I can in $O(k)$ time produce the smallest possible value and the largest:
while k:
k -= 1
temp = int((k)*(2*a+k-1)/2)
if s > b+temp:
yield b
b -= 1
s -= b
else:
yield s-temp
while k:
k -= 1
yield a+k
The last value generated by the above algorithm will be the smallest possible value. Also, the first value generated is the largest possible value.
Although, the largest can be done trivially (which is how I came up with the above greedy algorithm):
# (number of values)*(smallest + largest)/2 => sum {smallest,...,largest}
temp = int((k-1)*(2*a + k - 2)/2)
if s < b+temp:
max = b-temp
else:
max = b