The question is:
"Given an array A only contains integers Return the number of subarrays that contain at least k different numbers. Subarrays cannot be duplicated."
Example:
input array = {1, 2, 3, 4, 2} k = 3
output: 4
Explanation:
the number of the Subarray with at least K different numbers should be 4,
which are [1, 2, 3] [2, 3, 4] [3, 4, 2] [1, 2, 3, 4]
Right now what I can do is just find about the number of the subarray with exactly K different numbers:
class Solution {
public int subarraysWithKDistinct(int[] A, int K) {
return atMostK(A, K) - atMostK(A, K - 1);
}
private int atMostK(int[] A, int K) {
int i = 0, res = 0;
Map<Integer, Integer> count = new HashMap<>();
for (int j = 0; j < A.length; ++j) {
if (count.getOrDefault(A[j], 0) == 0) K--;
count.put(A[j], count.getOrDefault(A[j], 0) + 1);
while (K < 0) {
count.put(A[i], count.get(A[i]) - 1);
if (count.get(A[i]) == 0) K++;
i++;
}
res += j - i + 1;
}
return res;
}
}
But when the input be:
array = {1, 2, 3, 4, 2} k = 2
my code will not work correctly, but I don't know where to change. Any thoughts? Thanks!
Update: thanks to #MBo and others' answers, I used 2 pointers to fix this problem, but still cannot get the right answer with:
array = {1, 2, 3, 4, 2} k = 3 -> output: 6 (should be 4)
It looks like there are some duplicated substrings be counted, but I don't know how to fix it.
class Solution {
public static void main(String[] args) {
int[] A = {1, 2, 3, 4, 2};
int k = 3;
int res = helper(A, k);
System.out.println(res);
// output is 6, but should be 4
}
private static int helper(int[] A, int k) {
if (A == null || A.length == 0) return 0;
int n = A.length;
int res = 0;
int differentNumbers = 0;
Map<Integer, Integer> counter = new HashMap<>();
int j = 0; // j - 1 is the right point
for (int i = 0; i < n; i ++) {
while (j < n && differentNumbers < k) {
int numOfThisNumber = counter.getOrDefault(A[j], 0);
counter.put(A[j], numOfThisNumber + 1);
if (counter.get(A[j]) == 1) {
differentNumbers ++;
}
j ++;
}
if (differentNumbers == k) {
res += n - j + 1;
}
counter.put(A[i], counter.get(A[i]) - 1);
if (counter.get(A[i]) == 0) {
differentNumbers --;
}
}
return res;
}
}
You can combine your hashmap approach with method of two pointers (indices).
Set both indices into 0 and move right one, updating hashmap counts for values at the right end of interval until hashmap size reaches K. Fix right index.
Now move left index, decreasing counts corresponding to the values at left end. Before every step (including left=0) add size-right to result, because all subarrays starting from left and ending after right, do contain needed number of elements.
When some count becomes 0, remove value from hashmap, and fix left index.
Repeat with right index and so on.
I have an array of sorted integers. Given an integer N i need to place N largest elements further away from each other so that they have maximum space between each other. The remaining elements should be placed between these big items. For example, array of 10 with N=3 would result in [0, 5, 8, 2, 6, 9, 3, 7, 10, 4].
public static void main(String[] args) {
int[] start = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
int[] end = new int[10];
int N = 4;
int step = Math.round(start.length / N );
int y = 0;
int count = 0;
for (int i = 0; i < step; i++) {
for (int j = i; j<start.length; j = j + step) {
//System.out.println(j + " " + i);
if (count < start.length && start[count] != 0) {
end[j] = start[count];
count++;
}
}
}
System.out.println(end.toString());
}
You have an array of K elements. You have N max numbers you need to distribute. Then:
Step := K/N (removing the remainder)
Take any number from N maximum and insert it at Step/2 position.
Take other maximum numbers and insert it after the previous inserted maximum number at Step distance.
Giving [1,2,3,4,5,6,7,8,9,10]. So K = 10, N = 3. Then Step = 3. So the first maximum is placed at 3/2 position
[1,10,2,3,4,5,6,7,8,9]
Then other 2 are put at 3 distance from each other:
[1,10,2,3,9,4,5,8,6,7]
The code:
std::vector<int> Distribute(std::vector<int> aSource, int aNumber)
{
auto step = aSource.size() / aNumber; // Note integer dividing.
for (int i = 0; i < aNumber; ++i)
{
auto place = aSource.end() - i * step - step / 2;
aSource.insert(place, aSource.front());
aSource.erase(aSource.begin());
}
return aSource;
}
int main()
{
std::vector<int> vec{10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
auto res = Distribute(vec, 4);
for (auto e : res)
{
std::cout << e << ", ";
}
std::cout << std::endl;
}
Output:
6, 5, 4, 7, 3, 2, 1, 0, 8, -1, -2, -3, -4, 9, -5, -6, -7, -8, 10, -9, -10,
Algorithm reorder array according to given index
a[] = [50, 40, 70, 60, 90]
index[] = [3, 0, 4, 1, 2]
a= [60,50,90,40,70]
in O(n) and With out extra array/spaces
You'll need space for a temp variable and loop counters / indices. The usual "reorder" according to algorithm is also going to change index[] back to {0, 1, 2, 3, 4}.
Hint, noting the ordering of indices in index[].
{0, 1, 2, 3, 4}
index[] = {3, 0, 4, 1, 2}
The reordering can be done by following the "cycles". Start with index[0], and note the "cycles" if you look at index[0], then index[index[0]], and so on ...
// 1st cycle
index[0] == 3 // cycle starts at 0
index[3] == 1
index[1] == 0 // end of cycle since back at 0
// 2nd cycle
index[2] == 4 // cycle starts at 2
index[4] == 2 // end of cycle since back at 2
Example C code:
#include <stdio.h>
static int A[] = {50, 40, 70, 60, 90};
static int I[] = {3, 0, 4, 1, 2};
int main()
{
int i, j, k;
int tA;
/* reorder A according to I */
/* every move puts an element into place */
/* time complexity is O(n) */
for(i = 0; i < sizeof(A)/sizeof(A[0]); i++){
if(i != I[i]){
tA = A[i];
j = i;
while(i != (k = I[j])){
A[j] = A[k];
I[j] = j;
j = k;
}
A[j] = tA;
I[j] = j;
}
}
for(i = 0; i < sizeof(A)/sizeof(A[0]); i++)
printf("%d\n", A[i]);
return 0;
}
The same algorithm, but using swaps instead of moves (this is slower method).
#include <stdio.h>
#define swap(a, b) {(a)^=(b); (b)^=(a); (a)^=(b);}
static int A[] = {50, 40, 70, 60, 90};
static int I[] = {3, 0, 4, 1, 2};
int main()
{
int i, j, k;
/* reorder A according to I */
/* every swap puts an element into place */
/* last swap of a cycle puts both elements into place */
/* time complexity is O(n) */
for(i = 0; i < sizeof(A)/sizeof(A[0]); i++){
if(i != I[i]){
j = i;
while(i != (k = I[j])){
swap(A[j], A[k]);
I[j] = j;
j = k;
}
I[j] = j;
}
}
for(i = 0; i < sizeof(A)/sizeof(A[0]); i++)
printf("%d\n", A[i]);
return 0;
}
Say you are given a set of coins such as 4 10¢, 4 5¢, and 4 1¢.
You are asked to place these coins on a 12-hour analog clock face, where the next coin you place must be placed at X hours after the previous coin, where X is the value of the previous coin.
So if you place a 1¢ on 12, the next coin you place goes at 1. If you place a 5¢ on 1, the next coin you place goes at 6. And so on.
How can you maximize the number of coins that can be placed on the clock before the next coin would have to be placed in a slot that is already taken?
This is a problem I came across which I have been unable to solve except via exhaustive search. If the inputs are made to be arbitrary, exhaustive search fails quickly-- say it's an arbitrary number of coins of arbitrary various known denominations, with an arbitrary number of hours on the clock. Then you can't do exhaustive search anymore, because it becomes factorial time and fails on basis of excessive computational time requirements.
As maraca mentioned probably there isn't a much better solution than backtracking without more restrictions. Maybe with a larger number of coins of given denominations space can be covered with 'patterns'. Like coins [5, 10, 10, 5, 10, 10, 5, x] cover first 8 places and next coin is placed in similar location as first one. So the process can be repeated if there are enough coins.
Number of possible coin combinations in this case is not large at all. It is 12! / (4! * 4! * 4!) = 34650. For sure number explodes with larger parameters. Here is simple python code that solves 3 times larger problem which has possible coin combinations 3*10^15.
max_positions = []
max_order = None
def add_coin(coins, position, coin_order, occupied_positions, num_hours):
global max_positions, max_order
if position in occupied_positions or not coins:
# Can't place on that position or there is nothing more to place
if len(occupied_positions) > len(max_positions):
max_positions = occupied_positions
max_order = coin_order
return not coins # if all is covered return true to stop search
#
for c, num_coins in coins: # Try each coin
# Copy coins to new list and remove one used
c_coins = [x for x in coins if x[0] != c]
if num_coins > 1:
c_coins.append((c, num_coins-1))
# Next iteration
if add_coin(c_coins,
(position + c) % num_hours,
coin_order + [c],
occupied_positions + [position],
num_hours):
return True
def solve_coins(coins, num_hours):
global max_positions, max_order
max_positions = []
max_order = None
add_coin(coins, 0, [], [], num_hours)
print len(max_positions), max_positions, max_order
solve_coins([(1, 4), (5, 4), (10, 4)], 12)
solve_coins([(1, 8), (5, 8), (10, 8)], 24)
solve_coins([(1, 12), (5, 12), (10, 12)], 36)
output:
12 [0, 1, 6, 4, 2, 3, 8, 9, 7, 5, 10, 11] [1, 5, 10, 10, 1, 5, 1, 10, 10, 5, 1, 5]
24 [0, 1, 6, 16, 17, 3, 4, 14, 19, 5, 15, 20, 21, 2, 7, 8, 13, 18, 23, 9, 10, 11, 12, 22] [1, 5, 10, 1, 10, 1, 10, 5, 10, 10, 5, 1, 5, 5, 1, 5, 5, 5, 10, 1, 1, 1, 10, 10]
36 [0, 1, 6, 16, 17, 22, 23, 28, 2, 12, 13, 18, 19, 29, 34, 3, 8, 9, 10, 11, 21, 31, 5, 15, 20, 30, 35, 4, 14, 24, 25, 26, 27, 32, 33, 7] [1, 5, 10, 1, 5, 1, 5, 10, 10, 1, 5, 1, 10, 5, 5, 5, 1, 1, 1, 10, 10, 10, 10, 5, 10, 5, 5, 10, 10, 1, 1, 1, 5, 1, 10, 5]
// Expressing the coins as a list of buckets with the same modulo allows
// you to efficiently find the next coin to test and you don't start to
// calculate with the first penny and then do the same again starting
// with the second penny (or a 13-coin on a 12-clock), it is basically the same.
// Additionally it allows to remove and insert items at the current position in O(1).
// Also reverting is much better than copying whole states on each recursive call.
private class Bucket {
public int number;
public LinkedList<Integer> numbers = new LinkedList<>();
public Bucket(int number, int hours) {
this.number = number % hours;
numbers.add(number);
}
}
private LinkedList<Bucket> coins; // not using interface List as you are supposed to
private LinkedList<Integer> best, current; // because of removeLast()
private boolean[] occupied;
private int hours, limit;
public List<Integer> findBest(int[] coins, int hours) {
this.hours = hours;
// create buckets of coins with the same modulo
Integer[] c = Arrays.stream(coins).boxed().toArray( Integer[]::new );
// sort descending because a lot of small coins in a row are more likely to create
// an impassable area on the next pass around the clock
Arrays.sort(c, new Comparator<Integer>(){
public int compare(Integer a, Integer b) {
return Integer.compare(b.intValue() % hours, a.intValue() % hours);
}
});
this.coins = new LinkedList<>();
Bucket b = new Bucket(c[0].intValue(), hours);
this.coins.add(b);
int mod = c[0].intValue() % hours, coinCount = 1;
for (int i = 1; i < c.length; i++) {
int m = c[i].intValue() % hours;
if (m == mod) { // same bucket
b.numbers.add(c[i]);
} else { // new bucket
b = new Bucket(c[i].intValue(), hours);
this.coins.add(b);
mod = m;
}
coinCount++;
if (mod == 0) // don't need more than one 0 value
break;
}
best = new LinkedList<>();
current = new LinkedList<>();
occupied = new boolean[hours];
limit = coinCount < hours ? coinCount : hours; // max coins that can be placed
findBest(0);
return best;
}
private void findBest(int pos) {
if (best.size() == limit) // already found optimal solution
return;
if (occupied[pos] || current.size() == limit) {
if (current.size() > best.size())
best = (LinkedList<Integer>)current.clone();
return;
}
occupied[pos] = true;
for (int i = 0; i < coins.size(); i++) {
Bucket b = coins.get(i);
current.add(b.numbers.removeLast());
boolean removed = false;
if (b.numbers.size() == 0) { // bucket empty
coins.remove(i);
removed = true;
}
findBest((pos + b.number) % hours);
if (removed)
coins.add(i, b);
b.numbers.add(current.removeLast());
}
occupied[pos] = false;
}
Output for the given example: 10 10 5 1 1 1 5 10 10 1 5 5
Here is a slightly more optimized version in JavaScript where the list is implemented manually, so that you can really see why removing and adding the currend bucket is O(1). Because the list is always read in order it is superior to the array in this case. Whith an array you need to shift many elements or skip a lot of empty ones, depending how you implement it, not with a list of buckets. Should be a little easier to understand than the Java code.
var head, occupied, current, best, h, limit;
document.body.innerHTML = solve([1,1,1,1,5,5,5,5,10,10,10,10], 12);
function solve(coins, hours) {
h = hours;
coins.sort(function(a, b) {
let x = a % hours, y = b % hours;
if (x > y)
return -1;
if (x < y)
return 1;
return 0;
});
let mod = coins[0] % hours;
head = {num: mod, vals: [coins[0]], next: null};
let b = head, coinCount = 1;
for (let i = 1; i < coins.length && mod != 0; i++) {
let m = coins[i] % hours;
if (m == mod) {
b.vals.push(coins[i]);
} else {
b.next = {num: m, vals: [coins[i]], next: null};
b = b.next;
mod = m;
}
coinCount++;
}
limit = coinCount < hours ? coinCount : hours;
occupied = [];
for (let i = 0; i < hours; i++)
occupied.push(false);
best = [];
current = [];
solveRec(0);
return JSON.stringify(best);
}
function solveRec(pos) {
occupied[pos] = true;
let b = head, prev = null;
while (b !== null) {
let m = (pos + b.num) % h;
if (!occupied[m]) {
current.push(b.vals.pop());
let rem = false;
if (b.vals.length == 0) {
if (prev == null)
head = b.next;
else
prev.next = b.next;
rem = true;
}
solveRec(m);
if (current.length > best.length)
best = current.slice();
if (best.length == limit)
return;
if (rem) {
if (prev == null)
head = b;
else
prev.next = b;
}
b.vals.push(current.pop());
} else if (current.length + 1 > best.length) {
best = current.slice();
best.push(b.vals[b.vals.length - 1]);
}
prev = b;
b = b.next;
}
occupied[pos] = false;
}
I am still working on this, but it is already much better than O(n!). I will try to fit a new O() on it soon.
The concept is pretty simple, basically you create the smallest combos of numbers and then link them together into longer and longer strings of numbers until the next step is not possible.
A key to this working is that you don't track the front or end of a list of numbers, only the sum (and the inner sums due to their being calculated at earlier steps). so long as that sum is never divisible by clock, it will remain a clean solution.
Each step attempts to "splice" the smaller combos into the next size bigger:
(1,3), (3,1) -> (1,3,1), (3,1,3)
Here is a brief example (simplified) of what the algo is doing:
clock: 4
coins: 4
coins: 1,2,3,3
*bold pass, others are skipped for 1 of 3 reasons (not enough in population to build combo, sum divisible by clock, (in actual algo) prevent duplicates: (1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)
triples: (1,2,1), (2,1,2), (2,3,2), (3,2,3), (1,2,3), (2,3,3), (3,2,1), (3,3,2)
final combos:(1,2,3,x), (3,2,1,x)
This code is runnable standalone in c++ (but placeCoins is the algo):
I assume you will appropriate the algo to your purposes, but for anyone who wishes to run this cpp file, it will request clock size, coin count, and then after putting in coin count it will accept the next coin count number of inputs followed by enter as the coin values. The output will show the best counts, all orders at that count, and also during the algo it will show you the number of currently processing steps (which is where you can estimate complexity/ number of combos checked to see how much faster this is than exhaustive of any kind)
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <map>
using namespace std;
//min clock size 3
vector<vector<int>> placeCoins(int _clockSize, vector<int> _coins)
{
int totalCheckedCombos = 0;
vector<vector<int>> coinGroups;
vector<int> coinSet = _coins;
sort(coinSet.begin(), coinSet.end());
coinSet.erase(unique(coinSet.begin(), coinSet.end()), coinSet.end());
map<int, int> coinCounts;
for (int i = 0; i < coinSet.size(); i++)
{
coinCounts[coinSet.at(i)] = count(_coins.begin(), _coins.end(), coinSet.at(i));
}
cout << "pairs" << endl;
//generate fair pairs of coins
for (int i = 0; i < coinSet.size(); i++)
{
for (int ii = 0; ii < coinSet.size(); ii++)
{
if ((coinSet.at(i) + coinSet.at(ii)) % _clockSize != 0)
{
if (i == ii)
{
if (coinCounts[coinSet.at(i)] > 1)
{
coinGroups.push_back({ coinSet.at(i),coinSet.at(ii) });
}
}
else
{
coinGroups.push_back({ coinSet.at(i),coinSet.at(ii) });
}
}
}
}
cout << "combine" << endl;
//iteratively combine groups of coins
for (int comboSize = 3; comboSize < _clockSize; comboSize++)
{
totalCheckedCombos += coinGroups.size();
vector<vector<int>> nextSizeCombos;
for (int i = 0; i < coinGroups.size(); i++)
{
for (int ii = 0; ii < coinGroups.size(); ii++)
{
//check combo to match
bool match = true;
for (int a = 0; a < comboSize - 2; a++)
{
if (coinGroups.at(i).at(a+1) != coinGroups.at(ii).at(a))
{
match = false;
break;
}
}
//check sum
if (match)
{
vector<int> tempCombo = coinGroups.at(i);
int newVal = coinGroups.at(ii).at(coinGroups.at(ii).size()-1);
tempCombo.push_back(newVal);
if (coinCounts[newVal] >= count(tempCombo.begin(), tempCombo.end(), newVal))
{
if (accumulate(tempCombo.begin(), tempCombo.end(), 0) % _clockSize != 0)
{
nextSizeCombos.push_back(tempCombo);
}
}
}
}
}
if (nextSizeCombos.size() == 0)
{
//finished, no next size combos found
break;
}
else
{
cout << nextSizeCombos.size() << endl;
coinGroups = nextSizeCombos;
}
}
cout << "total combos checked: " << totalCheckedCombos << endl;
return coinGroups;
}
int main(int argc, char** argv) {
int clockSize;
int coinCount;
vector<int> coins = {};
cout << "enter clock size: " << endl;
cin >> clockSize;
cout << "count number: " << endl;
cin >> coinCount;
for (int i = 0; i < coinCount; i++)
{
int tempCoin;
cin >> tempCoin;
coins.push_back(tempCoin);
}
cout << "press enter to compute combos: " << endl;
cin.get();
cin.get();
vector<vector<int>> resultOrders = placeCoins(clockSize, coins);
for (int i = 0; i < resultOrders.size(); i++)
{
cout << resultOrders.at(0).size()+1 << endl;
for (int ii = 0; ii < resultOrders.at(i).size(); ii++)
{
cout << resultOrders.at(i).at(ii) << " , ";
}
cout <<"x"<< endl;
}
cin.get();
cin.get();
}
ps: although I debugged this to a stable state, it still could definitely use fine tuning and optimization, but that is variable to different languages, so I just got the algo to work and called it good enough. If you see something glaringly wrong or poor form, feel free to comment and i'll fix it (or edit it directly if you want).
Instead of a greedy approach, try the maximum result of choosing a coin vs. not choosing a coin.
def valueOfClock(capacity, coins, n, hour):
if (n == 0 or capacity == 0 or hour > 12):
return 0
# Choose next coin if value is greater than the capacity
if (coins[n-1] > capacity):
valueOfClock(capacity, coins, n-1, hours)
# Choose max value of either choosing the next coin or
# choosing the current coin
return max(valueOfClock(capacity, coins, n-1, hours),
valueOfClock(capacity-coins[n-1], coins, n-1, hours + coins[n-1]))
The problem I'm trying to solve is how do we find all the integer sets [a1, a2, ... ,am] so that
a1 + a2 + ... + am = N
and with the constraint ai >= 1
For example if M = 4, and N = 7 there are three answers
[1,1,1,4]
[1,1,2,3]
[1,2,2,2]
Since you have to print all the sets that sum to N. You can employ a complete search algorithm using recursion. In the following code, M is the number of numbers in the set and N is the sum required.
int M;
int N;
void run(){
M = 4;
N = 7;
int[] arr = new int[M];
print(arr, 0, N, 1);
}
// req holds the required sum for the numbers in the array from arr[from]
// to arr[M-1].
// "last" holds the last value that we had put in the array.
// The first call to the array will be with last=1.
void print(int[] arr, int from, int req, int last){
// Reached the end of the array and sum required 0.
if(from==M && req==0){
System.out.println(Arrays.toString(arr));
return;
}
// Either reached the end of the array but sum is not equal to N
// Or if we have not reached the end of the array but sum has already
// become more than or equal to N.
if(from==M || req<=0){
return;
}
for(int i=last; i<=req; i++){
arr[from] = i;
print(arr, from+1, req-i, i);
}
}
Output for M=4 and N=7:
[1, 1, 1, 4]
[1, 1, 2, 3]
[1, 2, 2, 2]
Output for M=3 and N=10:
[1, 1, 8]
[1, 2, 7]
[1, 3, 6]
[1, 4, 5]
[2, 2, 6]
[2, 3, 5]
[2, 4, 4]
[3, 3, 4]
Answer for the problem in the link, just got accepted.
The idea is simple, assume that we know the maximum value for each section is X, and we want to find a way to divide these cabinets to achieve that , we can greedily divide them as follow:
Starting from first cabinet, iterating through each cabinet, until the total from first to ith cabinet is greater than X. So this is the first section, similarly, we can select other sections. This greedy will always find a solution (if exists).
Finally, we can using binary search to adjust the value of X, decrease X if we can find a way to divide the cabinets, or increase X if we cannot find one.
Here is the code in Java:
public class FairWorkload {
public int getMostWork(int[] folders, int workers) {
int[] data = new int[folders.length];
data[0] = folders[0];
for (int i = 1; i < data.length; i++) {
data[i] = data[i - 1] + folders[i];
}
if (workers == 1) {
return data[data.length - 1];
}
int start = 0;
int end = data[data.length - 1];
int result = Integer.MAX_VALUE;
while (start <= end) {
int mid = (start + end) / 2;
int index = 0;
for (int k = 0; k < workers && index < data.length; k++) {
int less = index > 0 ? data[index - 1] : 0;
int temp = index;
for (int i = index; i < data.length; i++) {
if (data[i] - less <= mid) {
temp = i;
} else {
break;
}
}
// System.out.println(data[temp] - less + " " + mid);
if(data[temp] - less > mid){
index = -1;
break;
}
index = temp + 1;
}
//System.out.println(mid + " " + index);
if (index != data.length) {
start = mid + 1;
} else {
result = Math.min(result, mid);
end = mid - 1;
}
}
return result;
}
public static void main(String[] args) {
int[] data = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1000};
System.out.println(new FairWorkload().getMostWork(data, 2));
}
}
One possible solution uses a counting technique, finding the rightmost term that satisfies [i] <= [length-1] - 2, and then flattening out all other terms to the right as much as possible, keeping a[i] <= a[i+1].
import java.util.Arrays;
public class test {
public static void main(String[] args) {
test t = new test();
t.go();
}
private void go() {
int w = 3;
int sum = 10;
int[] terms = new int[w];
for (int i = 0; i < terms.length; i++) {
terms[i] = 1;
}
terms[w-1] = sum - w + 1;
System.out.println(Arrays.toString(terms));
for (int i = right_index(terms); i>=0; i = right_index(terms)) {
terms[i]++;
int a = terms[i];
int overflow = -1;
// balance all the terms to the right
for (int j = i+1; j < terms.length-1; j++) {
overflow += terms[j] - a;
terms[j] = a;
}
terms[terms.length-1] += overflow;
System.out.println(Arrays.toString(terms));
}
}
// find the rightmost index i, where [i] <= [ia.length-1] - 2
private int right_index(int[] ia) {
int max = ia[ia.length-1];
for (int i = ia.length - 1; i >= 0; i--) {
if (ia[i] <= max - 2)
return i;
}
return -1;
}
}