zoukankan      html  css  js  c++  java
  • leetcode 15三数之和 神仙做法?等再刷刷回头看

    class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            if (nums.length < 3) return Collections.emptyList(); 
            List<List<Integer>> res = new ArrayList<>(); 
            int minValue = Integer.MAX_VALUE; 
            int maxValue = Integer.MIN_VALUE; 
            int negSize = 0, posSize = 0; 
            int zeroSize = 0; 
            for (int v : nums) { 
                if (v < minValue) minValue = v; 
                if (v > maxValue) maxValue = v; 
                if (v > 0) posSize++; 
                else if (v < 0) negSize++; 
                else zeroSize++; 
            }
            if (zeroSize >= 3) res.add(Arrays.asList(0, 0, 0));//输出 三个 0 的情况 
            if (negSize == 0 || posSize == 0) return res;
            //此时minValue一定为负数,maxValue一定为正数
            //如果maxValue > -2*minValue,那么大于 -2*minValue的元素肯定不会是答案,可以排除掉,所以更新maxValue
            if (minValue * 2 + maxValue > 0) maxValue = -minValue * 2; 
            //同理更新minValue
            else if (maxValue * 2 + minValue < 0) minValue = -maxValue * 2;
            //自己构建一个hashmap,值表示元素重复次数,注意java数组默认值为 0
            int[] map = new int[maxValue - minValue + 1];
            int[] negs = new int[negSize];
            int[] poses = new int[posSize];
            negSize = 0;
            posSize = 0;
            for (int v : nums) {
                if (v >= minValue && v <= maxValue) {//只保留在[minValue,maxValue]区间内的元素
                    if (map[v - minValue]++ == 0) {//计数加去重
                        if (v > 0) poses[posSize++] = v;//poses数组存所有去重后的正值
                        else if (v < 0) negs[negSize++] = v;//negs数组存所有去重后的负值 
                    }
                }
            }
            //正负数两数组排序
            Arrays.sort(poses, 0, posSize);
            Arrays.sort(negs, 0, negSize);
            int basej = 0;
            for (int i = negSize - 1; i >= 0; i--) {//负数数组从后往前遍历
                int nv = negs[i];//nv为当前负数值
                //minp = -nv/2,相当于三元组中另外两元素的平均值,即为另两个元素中较小值的上界,较大值的下界
                int minp = (-nv) >>> 1;
                //定位到正数数组中值刚好小于平均值的元素(这个地方应该还可以优化为使用二分查找)
                while (basej < posSize && poses[basej] < minp) basej++;
                for (int j = basej; j < posSize; j++) {//正数数组从大于等于平均值的元素开始遍历
                    int pv = poses[j];//pv 为当前正数值
                    int cv = 0 - nv - pv;//cv 为要寻找的另一个值
                    //目标值 cv 应该在 [nv,pv] 当中
                    //如果不限制cv<=pv,当nv为奇数时,有可能会重复输出
                    if (cv >= nv && cv <= pv) {
                        if (cv == nv) {
                            if (map[nv - minValue] > 1)//两个相同的负数和一个正数的情况
                                res.add(Arrays.asList(nv, nv, pv));
                        } else if (cv == pv) {
                            if (map[pv - minValue] > 1)//两个相同的正数和一个负数的情况
                                res.add(Arrays.asList(nv, pv, pv));
                        } else {
                            if (map[cv - minValue] > 0)//三个不同元素的情况
                                res.add(Arrays.asList(nv, cv, pv));
                        }
                    } else if (cv < nv) break;//如果 cv 小于 nv了,表明这种情况会在后面寻找,为避免重复输出,跳出循环
                }
            }
            return res;
        }
    }
  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/doyi111/p/11791895.html
Copyright © 2011-2022 走看看