• LeetCode 三数之和 — 优化解法


    LeetCode 三数之和 — 改进解法

    题目:给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
    注意:答案中不可以包含重复的三元组。
    例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
    满足要求的三元组集合为:
    [ [-1, 0, 1], [-1, -1, 2] ]

     最开始做的解法是先将整个数组排序;然后遍历前两个数(a和b)的所有情况(n^2);对于第三个数,则从剩余的数中(即从第二个数下一个位置开始到末尾)利用二分查找出是否存在数字 -(a+b)即可。 复杂度O(n^2·logn) :

    class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            
            
            List<List<Integer>> ans = new ArrayList<List<Integer>>();
            Arrays.sort(nums);
            
            Map<Integer,Integer> mi = new HashMap();
            for(int i=0;i<nums.length-1;i++) {
                if(mi.get(nums[i]) != null) continue; //记录i下标读过的数字
                mi.put(nums[i],1);
                
                Map<Integer,Integer> mj = new HashMap();    
                for(int j=i+1;j<nums.length;j++) {
                    if(mj.get(nums[j]) != null) continue; //记录j下标读过的数字
                    mj.put(nums[j],1);
                    
                    int temp = -(nums[i]+nums[j]);
                    if(bSearch(nums,j+1,nums.length-1,temp) == false) continue; //二分搜索j下标之后的区间是否有数字temp
                    ans.add(Arrays.asList(nums[i],nums[j],temp));
                }
            }
            
            return ans;
            
        }
    
        //二分算法
        public boolean bSearch(int[] nums,int s,int e,int key) {
            int start=s,end=e,mid;
            while(start<=end){
                mid = (start+end)/2;
                if(key < nums[mid]) end=mid-1;
                else if(key > nums[mid]) start=mid+1;
                else if(key == nums[mid]) return true;
            }
            return false;
        }
    }
    

    里面有两个用了哈希的地方,所以时间复杂度应该还要乘上一个常数K...(解数组相关的题感觉总有些依赖哈希的方法=_= ...)




     最近做了另一个数组区间相关的题目,受其解法的启发,打算对这道题解法进行优化。
     还是先对数组进行排序;对第一个数字(a)进行遍历,而然后在剩余的数中用前后指针的方法找出两个和为-a的数字:两个指针left和right;left初始化为数字a的下一位置,right为最后一个位置。比较nums[left]+nums[right]+a和0的大小;如果大于0则right--,小于就left++。 其中在添加结果集时需考虑去重问题,用个哈希判断是否有重复就行了,复杂度O(n^2·K) :

    class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            
            List<List<Integer>> ans = new ArrayList<List<Integer>>();
            Arrays.sort(nums);
            
            Map<Integer,Integer> mi = new HashMap();
            for(int i=0;i<nums.length-2;i++) {
                if(mi.get(nums[i]) != null) continue; //记录i下标读过的数字
                mi.put(nums[i],1);
                
                Map<Integer,Integer> mj = new HashMap();
                int l = i+1, r = nums.length-1, temp;
                while(l<r) {
                    temp = nums[i] + nums[l] + nums[r];
                    if(temp < 0) {
                        l++;
                    } else if(temp > 0) {
                        r--;
                    } else {
                        if((mj.get(nums[l])) == null) {
                            ans.add(Arrays.asList(nums[i], nums[l], nums[r]));
                            mj.put(nums[l], 1);
                            
                        }
                        l++; r--;
                    }
                }
            }
            
            return ans;
            
        }
    }
    
  • 相关阅读:
    github提交用户权限被拒
    vue数据响应式的一些注意点
    总结一下做移动端项目遇到的坑
    react-router
    promise-async-await
    递归函数
    Linux基础
    所有的数据处理都是map-reduce
    Mac下配置JAVA_HOME
    MySQL高级
  • 原文地址:https://www.cnblogs.com/geek1116/p/10172313.html
Copyright © 2020-2023  润新知