0

Given a sorted integer array without duplicates, return the summary of its ranges for consecutive numbers.

For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"].

I proposed the following solution:

public List<String> summaryRanges(int[] nums) {
    if (nums == null){
        return null;
    }
    if (nums.length == 0){
        return new ArrayList<>();
    }
    if (nums.length == 1){
        List<String> arr = new ArrayList<>();
        arr.add(Integer.toString(nums[0]));
        return arr;
    }

    List<String> summary = new ArrayList<>();
    int n = nums.length;
    int begin = nums[0];
    int end;

    for (int i = 1; i < n; i++) {
        if (nums[i] - nums[i-1] > 1) {
            end = nums[i-1];
            if (begin == end){
                summary.add(Integer.toString(begin));

            }
            else{
                summary.add(Integer.toString(begin) + "->" + Integer.toString(end));
            }
            begin = nums[i];
        }
    }
    if (nums[n-1] - nums[n-2] > 1){
        summary.add(Integer.toString(nums[n-1]));
    }
    else{
        summary.add(Integer.toString(begin) + "->" +Integer.toString(nums[n-1]));
    }

    return summary;
}

This program fails for the following example: [-2147483648, -2147483647, 2147483647] (returns the wrong answer: ["-2147483648->2147483647"])

I suspect this is due to an overflow issue, but I can't figure out why exactly. On the opposite, this example solution I found passes this test case:

public List<String> summaryRanges(int[] nums) {
    List<String> result = new ArrayList<String>();

    if(nums == null || nums.length==0)
        return result;

    if(nums.length==1){
        result.add(nums[0]+"");
    }

    int pre = nums[0]; // previous element   
    int first = pre; // first element of each range

    for(int i=1; i<nums.length; i++){
            if(nums[i]==pre+1){
                if(i==nums.length-1){
                    result.add(first+"->"+nums[i]);
                }
            }else{
                if(first == pre){
                    result.add(first+"");
                }else{
                    result.add(first + "->"+pre);   
                }

                if(i==nums.length-1){
                    result.add(nums[i]+"");
                }

                first = nums[i];
            }

            pre = nums[i];
    }

    return result;
}

Why does this solution pass this test and not the one I proposed?

3
  • 1
    StackOverflow isn't for debugging help (sorry). Step through this with a debugger: check your variables through the "Variables" view as you step through the execution of your program with a step filter. StackOverflow questions should be about specific questions, not asking people to look through a block of code for your issue Commented Jul 26, 2015 at 17:19
  • @VinceEmigh didn't you just help them debug? :P Commented Jul 26, 2015 at 17:49
  • @dimo414 Told him how to debug. Ain't nobody got time for debuggin strangers' code ;) Commented Jul 26, 2015 at 17:54

2 Answers 2

1

Yes, indeed, the problem is overflow.

The difference between your programs is, basically, that you are using the test:

nums[i] - nums[i-1] > 1

whereas the other program uses

nums[i]==pre+1

In a purely mathematical world, there should be no difference between comparing y to x+1 and comparing y-x to 1, but in the world of 32-bit integer, there is a big difference.

When you get to the numbers -Integer.MAX_VALUE and Integer.MAX_VALUE, which is what the numbers in your example array are, then your comparison is:

Integer.MAX_VALUE - -Integer.MAX_VALUE > 1

As the minus signs cancel each other, this means 2 * Integer.MAX_VALUE, which is larger than an int can hold, and you get an overflow. The result is -2 and that's not greater than 1.

In the other program's way, you would be asking whether

Integer.MAX_VALUE == - Integer.MAX_VALUE + 1

The left hand part is, of course, a legal integer. The right hand value is also a legal integer, because you are just stepping away from the minimum. Thus, no overflow, and the comparison would return false, which is good.

Sign up to request clarification or add additional context in comments.

Comments

0

Can you try using absolute values wherever checking the differences:

Math.abs(nums[i]) - Math.abs(nums[i-1])

I suppose this looks like an issue here in case of negative numbers.

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.