了解Java中的溢出问题

时间:2015-07-26 17:09:38

标签: java integer-overflow

  

给定一个没有重复的排序整数数组,返回摘要   它的连续数字范围。

     

例如,给定[0,1,2,4,5,7],返回[“0-> 2”,“4-> 5”,“7”]。

我提出了以下解决方案:

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;
}

此程序对以下示例失败:[-2147483648, -2147483647, 2147483647](返回错误答案:["-2147483648->2147483647"]

我怀疑这是由于溢出问题,但我无法弄明白为什么。相反,我发现的这个示例解决方案通过了这个测试用例:

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;
}

为什么这个解决方案通过了这个测试,而不是我提出的那个?

2 个答案:

答案 0 :(得分:1)

是的,确实,问题是溢出。

您的程序之间的区别基本上是您正在使用测试:

getElementsByTagName

而另一个程序使用

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

在纯粹的数学世界中,将nums[i]==pre+1 y进行比较并将x+1y-x进行比较之间应该没有区别,但在32位整数的世界中,有很大的不同。

当您到达数字1-Integer.MAX_VALUE时,这是您的示例数组中的数字,那么您的比较是:

Integer.MAX_VALUE

由于减号相互抵消,这意味着Integer.MAX_VALUE - -Integer.MAX_VALUE > 1 大于2 * Integer.MAX_VALUE可以容纳的,并且您会收到溢出。结果是-2,并且不大于1.

在另一个程序中,你会问是否

int

左手部分当然是一个合法的整数。右手值也是一个合法的整数,因为你只是偏离了最小值。因此,没有溢出,比较将返回Integer.MAX_VALUE == - Integer.MAX_VALUE + 1 ,这是好的。

答案 1 :(得分:0)

在检查差异的地方,您可以尝试使用绝对值:

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

我认为这在负数的情况下看起来像是一个问题。