• LeetCode数字之和总结


    此总结包含题目(两数之和,三数之和,最接近的三数之和,四数之和,两数之和 II - 输入有序数组

    1.两数之和

    /*
    给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。
    你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
    */
     public int[] twoSum(int[] nums, int target) {
          //  map中的 key 某个之前的数   value 这个数出现的位置
         HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
         for(int i = 0;i < nums.length;i++){
             int k =  target - nums[i];
             if(map.containsKey(k)){
                 return new int[]{map.get(k),i};
             }
             map.put(nums[i],i);
         }
         return new int[] { -1, -1 };    
     }
    

    2. 三数之和

    /*
    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
    */
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<integer>> list = new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        for(int i = 0;i < nums.length - 2;i++){
            if(nums[i]>0) break;
            if(i==0||nums[i] != nums[i-1]){
                List<List<integer>> tmp = mytwoSum(nums,i+1,-nums[i]);
                for(List<integer> cur:tmp){
                    cur.add(0,nums[i]);
                    list.add(cur);
                }
            }
        }
        rerurn list;
    }
    
    public List<List<Integer>> mytwoSum(int[] nums, int begin, int target) {
        int L = begin;
        int R = nums.length-1;
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        while(L<R){
            if(nums[L] + nums[R] < target){
                L++;
            }else if(nums[L] + nums[R] > target){
                R--;
            }else{ // 进入else表示找到了
                // 1. begin是第一个开始 2. 当前和前一个不等
                if(L==begin||nums[L-1] != nums[L]){
                    List<Integer> M = new ArrayList<Integer>();
                    M.add(nums[L]);
                    M.add(nums[R]);
                    ans.add(M);
                }
                L++;
            }
        }
        return ans;
    }
    

    3. 最接近的三数之和

    /*
    给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
    */
    public int threeSumClosest(int[] nums, int target) {
        int sum1 = nums[0] + nums[1] + nums[2]; //首先随便计算三数之和
        int diff = Math.abs(target - sum1); // 差值
        Arrays.sort(nums);
        for(int i = 0;i < nums.length - 2;i++){
            if(i > 0 && nums[i-1] == nums[i]) continue;
            int m = i + 1;
            int n = nums.length -1;
            while(m<n){
                int tmp = nums[i] + nums[m] + nums[n];
                int t_diff = Math.abs(target - tmp);
                if(t_diff < diff){
                    diff = t_diff;
                    sum1 = tmp;
                }
                if(tmp < target){
                    m++;
                }else{
                    n--;
                }
            }
        }
        return sum1;
    }
    

    4. 四数之和

    /*
    给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] :
    0 <= a, b, c, d < n
    a、b、c 和 d 互不相同
    nums[a] + nums[b] + nums[c] + nums[d] == target
    */
    
    public List<List<Integer>> fourSum(int[] nums, int target) {
    	List<List<Integer>> list = new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        for(int i = 0;i < nums.length - 3;i++){
            if(i==0||nums[i] != nums[i-1]){
                List<List<Integer>> tmp = myThreeSum(nums,i+1,target-nums[i]);
                for(List<Integer> cur:tmp){
                    cur.add(0,nums[i]);
                    list.add(cur);
                }
            }
        }
        return list;	
    }
    
    public List<List<Integer>> myThreeSum(int[] nums, int begin, int target) {
    	List<List<Integer>> list = new ArrayList<List<Integer>>();
        for(int i = begin;i < nums.length - 2;i++){
            if(i == begin||nums[i] != nums[i-1]){
                List<List<Integer>> tmp = mytwoSum(nums,i+1,target-nums[i]);
                for(List<Integer> cur:tmp){
                    cur.add(0,nums[i]);
                    list.add(cur);
                }
            }
        }
        return list;
    }
    
    public List<List<Integer>> mytwoSum(int[] nums, int begin, int target) {
        int L = begin;
        int R = nums.length-1;
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        while(L<R){
            if(nums[L] + nums[R] < target){
                L++;
            }else if(nums[L] + nums[R] > target){
                R--;
            }else{ // 进入else表示找到了
                // 1. begin是第一个开始 2. 当前和前一个不等
                if(L==begin||nums[L-1] != nums[L]){
                    List<Integer> M = new ArrayList<Integer>();
                    M.add(nums[L]);
                    M.add(nums[R]);
                    ans.add(M);
                }
                L++;
            }
        }
        return ans;
    }
    
    
    // 解法二
    public List<List<Integer>> fourSum2(int[] nums, int target) {
            List<List<Integer>> list = new ArrayList<List<Integer>>();
    		if(nums.length<4) return list;
    		Arrays.sort(nums);
    		for(int i=0;i<nums.length-3;i++) {
                if (i > 0 && nums[i] == nums[i - 1]) continue;
    			for(int j=i+1;j<nums.length-2;j++) {
                    if (j > i+1 && nums[j] == nums[j - 1]) continue;
    				int m = j+1;
    				int n = nums.length-1;
    				while(m<n) {
    					int sum = nums[i]+nums[j]+nums[m]+nums[n];
    					if(sum==target) {
    						List<Integer> tmpIntegers = new ArrayList<Integer>();
    						tmpIntegers.add(nums[i]);
    						tmpIntegers.add(nums[j]);
    						tmpIntegers.add(nums[m]);
    						tmpIntegers.add(nums[n]);
    						list.add(tmpIntegers);
                            while (m < n && nums[m] == nums[m + 1]) ++m;
    	                    while (m < n && nums[n] == nums[n - 1]) --n;
                            m++;
    						n--;
    					}else if (sum<target) {
    						m++;
    					}else {
    						n--;
    					}
    				}
    			}
    		}
    		
    		return list;
        }
    

    5. 两数之和 II - 输入有序数组

    /*
    给定一个已按照 非递减顺序排列  的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
    
    函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
    */
    public int[] twoSum(int[] numbers, int target) {
            int point_i = 0;
            int point_j = numbers.length-1;
            while(point_i<point_j){
                if(numbers[point_i]+numbers[point_j] == target) return new int[]{point_i+1,point_j+1};
                else if(numbers[point_i]+numbers[point_j] < target) point_i++;
                else{
                    point_j--;
                }
            }
            return new int[]{point_i,point_j};
     }
    

    6. 总结

    此类题目主要用到哈希表来存储元素,以达到快速判断的目的,此外还有利用已经排好序的数组后的特性,利用双指针来加速检索符合要求的元素

  • 相关阅读:
    apache 虚拟主机配置(根据不同的域名映射到不同网站)
    Tortoise SVN 使用笔记
    Apache 根据不同的端口 映射不同的站点
    jquery 获取当前元素的索引值
    修改ThinkPHP的验证码类
    NetBeans无法使用编码GBK安全地打开该文件
    在win2003下apache2.2无法加载php5apache2_4.dll
    我看软件工程
    PHP函数参数传递(相对于C++的值传递和引用传递)
    Notepad++ 使用正则表达式查找替换字符串
  • 原文地址:https://www.cnblogs.com/wailaifeike/p/15429406.html
Copyright © 2020-2023  润新知