1

I am trying to solve a coding problem where I need to repeatedly double a number (original) as long as it exists in an integer array. To make the lookup faster, I am inserting all elements of the array into a HashSet. My understanding is that this should allow constant-time contains() checks.

However, when I put the doubling condition inside the loop that builds the set, my code fails on certain inputs. Here is the code:

public int findFinalValue(int[] nums, int original) {
    Set<Integer> set = new HashSet<>();
    for (int num : nums) {
        set.add(num);
        if (set.contains(original)) {
            original *= 2;
        }
    }
    return original;
}

For example, with nums = [5,3,6,1,12] and original = 3, this code returns 12, but the correct result should be 24 because 3 → 6 → 12 → 24 (all appear in the array).

When I move the condition outside the loop like this:

while (set.contains(original)) {
    original *= 2;
}

…it works correctly.

My question is:

Why does checking contains(original) inside the same loop where the set is being built cause incorrect behavior?
I assumed adding elements one by one and checking in the same pass should logically work, since ultimately the same set gets built.

Is there some detail about iteration order, timing of updates, or HashSet behavior that I am misunderstanding?

Any explanation about why the logic only works after the full set is constructed would be greatly appreciated.

New contributor
Gurkirat Singh is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
4
  • 3
    I can't reproduce that behavior with your input - see programiz.com/online-compiler/4Gw0KLm0LNDUA for example. It's really important that people can reproduce the results you're seeing. The answer from teapot418 is absolutely right, but doesn't explain the result you're supposedly seeing for [5,3,6,1,12]. Commented Nov 25 at 16:55
  • Regardless, I think there might be a flaw in checking for membership in a partial set. What happens with an array like [12,5,3,6,1] when original is 3? I think you have to build the entire set first. Commented Nov 25 at 18:13
  • Why not take the two subtasks apart? First add all the numbers. Then start checking if original is in the set and double it as long as it is. Would seem simpler to argue about to me. Commented Nov 26 at 6:41
  • Your assumption is wrong. It doesn't make any difference if ultimately the same set gets built, if you are using the partial set before it is properly built. Commented Nov 26 at 17:25

1 Answer 1

3

The argument does not quite work for your values. If you are sure about those, try preparing a minimal reproducible example.

But let's assume nums = [5,3,1,12,6] instead. When adding 6, the current value will be checked against 6 once and doubled to 12. 12 will not be checked against the set again and gets returned.

You will do at most one doubling per loop. Adding one value can reveal the need to perform multiple doublings. This can happen too late in the loop to get you the right result in time.

You could fix that by making the inner if to a while as in:

    for (int num : nums) {
        set.add(num);
        while (set.contains(original)) {
            original *= 2;
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.