LeetCode--两数之和 java用时极限挑战

问题:

        LeetCode两数之和

        述:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

          范例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解决:

        问题很简单,寻找2个不同(位置不同)的数之和等于目标值,并返回对应结果。由于题目假设每个输入只对应一种答案,且同样的元素不能被重复利用,我们可以再找到结果后就返回结果。

        1.2个for循环判断
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int length = nums.length;
        int[] result ={0,0};
        for(int i = 0; i < (length - 1); i++){
            for(int j = i + 1 ;j < length; j++){
                if((nums[i] + nums[j]) ==  target){
                    result = new int[]{i,j};
                }
            }
        }
        return result;
    }
}

        用时反馈


        嗯,结果是通过了,用时有点惨目忍睹。


        2.考虑到题目限制只有一个可行解,我们在寻找到结果时就可以直接break跳出。
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int length = nums.length;
        int[] result ={0,0};
        Boolean flag = false;
        for(int i = 0; i < (length - 1); i++){
            if(flag) break;
            for(int j = i + 1 ;j < length; j++){
                if((nums[i] + nums[j]) ==  target){
                    flag = !flag;
                    result = new int[]{i,j};
                    break;
                }
            }
        }
        return result;
    }
}

用时结果


        看起来比之前好点。

        3修改部分细节
class Solution {
    public int[] twoSum(int[] nums, int target) {
        for(int i = 0; i < (nums.length - 1); i++){
            for(int j = i + 1 ;j < nums.length; j++){
                if((nums[i] + nums[j]) ==  target){
                    return new int[]{i,j};
                }
            }
        }
        return new int[]{0,0};
    }
}

        时间结果


        从时间统计上来看,到了第二坡度的顶端,2个for循环的时间本质上的提升比较困难。

        补充:将length = nums.length写入for循环的初始条件里还要快点,测试能到30ms,但很遗憾还是差太多。


        4考虑到如果存在相同的数,就可以跳过后面的2级循环,修改代码如下
class Solution {
    public int[] twoSum(int[] nums, int target) {
        A:for(int i = 0; i < (nums.length - 1); i++){
            for(int k = 0; k < i;k++){
                if(nums[k] == nums[i]) continue A;
            }
            for(int j = i + 1 ;j < nums.length; j++){
                if((nums[i] + nums[j]) ==  target){
                    return new int[]{i,j};
                }
            }
        }
        return new int[]{0,0};
    }
}

        时间结果:


        然而很遗憾,这种优化存在不稳定情况,多余的判断(每个数都要判断)消耗的时间可能要比循环一次(存在相同的数)所消耗的时间更多。

        5 好吧,我们直接看最快的3ms的算法吧o(╥﹏╥)o
class Solution {
    public int[] twoSum(int[] nums, int target) {
    int[] res = new int[2];
        if (nums == null || nums.length < 2)
            return res;

        int max = nums[0];
        int min = nums[0];
        for (int i = 0; i < nums.length; i++) {
            if (max < nums[i])
                max = nums[i];
            if (min > nums[i])
                min = nums[i];
        }

        int[] index = new int[max - min+1];
        target = target ;
        int other =0;
        for (int i = 0; i < nums.length; i++) {
                other = target - nums[i];
                if(other < min || other > max) {
                    continue;
                }
            if(index[other- min] > 0) {
                res[0] = index[other -min ]-1;
                res[1] = i;
                return res;
            }
            index[nums[i] - min] = i+1;
        }
        return res;
    }
    
}

简单解释一下这个代码:

        1边界条件判断(说实话,如果仅从LeetCode这道题出发,20个测试样例并不存在边界)

        2求最大最小值,建立一个从最小到最大中间数的个数的数组index(后面有用)

        3对每个数进行循环,用求取值减去循环值,判断是否在最大最小值之间

        4对每个数减去最小值得到结果就在对应的index上+1,即判断是否存在

        5再用求取值减去当前i得到的值去在index上判断是否存在

    典型的空间换时间方法,只有一层for循环,用备忘录信息表进行搜索判断。

猜你喜欢

转载自blog.csdn.net/u014418725/article/details/80443825
今日推荐