Leetcode 15:三元素之和为零-java代码

题目描述:

给定由N个整数组成的数组nums,找出三个元素之和为0的三元组(非重复序列),并记录这样的三元组的数量。

threeSum算法

//ThreeSum 用于统计一个数组中和为 0 的三元组数量。
	public interface threeSum {
	    int count(int[] nums);
	}

算法一:threeSumLow()

分析:ThreeSumLow 算法内循环(三层循环 for) 判断if(num[i] + num[j] + num[k] = 0)语句是否成立,总共执行次数为N(N-1)(N-2) [其中N为数组的长度,即.N = nums.length],因此该算法近似执行为N3/6,时间复杂度为O(N3)。

解题思路

  • 三个元素分别用一层循环;
  • 第一层循环从元素nums[0]开始;
  • 因为非重复,则第二个元素必定是在第一个元素之后的元素,所以从nums[0+1]开始循环;同理,第三个元素从nums[0+1+1]=nums[2]开始;
  • 第三组循环一直循环结束后,第二个元素下标+1前进一位进行循环,第二组循环结束后,第一个元素下标+1进行循环,直到第一组循环结束。
public class threeSumSlow implements threeSum {
    //count(int[] nums)函数是记录三个元素之和为0的三元组数量
    public int count(int[] nums) {
        int N = nums.length;
        int cnt = 0;//初始化三元组数量为0
        for (int i = 0; i < N; i++) {//从数组起始位0开始,即数组的第一个元素开始
            for (int j = i + 1; j < N; j++) {//第二层循环,从第二个元素往后
                for (int k = j + 1; k < N; k++) {//第三层循环,从第三个元素之后开始
                    if (nums[i] + nums[j] + nums[k] == 0) {//判断三个元素之和是否为零
                        cnt++;//如果三个元素之和为0,数量+1;如果不为0,继续第三层循环直到k=N
                    }
                }
            }
        }
        return cnt;
    }
}

算法二:threeSumBinarySearch()

分析:先将数组进行排序,然后对数组中两个元素求和,并用二分查找方法查找是否存在该和的相反数,如果存在,就说明存在三元素之和为 0 的三元素。二分查找只有数组不含有相同元素才能使用这种解法,否则二分查找的结果会出错。该方法可以将 ThreeSum 算法时间复杂度降为 O(N2logN)。

解题思路

  • 两层循环+一次二分查找算法;
  • 将数组元素进行sort()函数排序;
  • 算法一中同样的方法进行二次循环,对数组中两个元素求和赋给target;
  • 执行二分查找算法判断数组中是否存在target的相反数。
public class threeSumBinarySearch implements ThreeSum {
	public  int cout(int[] nums) {
		Arrays.sort(nums);\\通过Arrays.sort()函数将数组nums进行排序
		int N = nums.length;
		int cnt = 0;
		//进行二次循环(内循环)
		for (int i = 0; i < N; i++) {
		for (int j = i + 1; j < N; j++) {
				int target = -(num[i] + nums[j]);//求数组内两个元素之和,赋给target
				int index = binarySearch.search(nums, target);//调用函数BinarySearch.search()求与target相加为0的元素的小标
				//保证求出的下标大于 j,否则会出现重复统计。
				if (index > j) {
				cnt++;//如果三个元素之和为0,数量+1;如果不为0,继续第二层循环直到j=N
				}
			}
		}
		return cnt;
	}
}
//BinarySearch 二分查找算法
public class binarySearch {
	public static int search(int[] nums, int target) {
	int low = 0, high = nums.length - 1;//low、high分别表示为数组左侧低阶和数组右侧高阶的下标
		while (low <= high) {
			int mid = low + (high - 1)/2;//将数组从中间二分
			if (target == nums[mid]) {//如果中间元素满足相反数条件,直接返回
			return mid;
			} else if (target > nums[mid]) {//如果中间元素<相反数,则继续[mid+1, high]二分循环查找
			low = mid + 1;
			} else {//如果中间元素>相反数,则继续[low, mid-1]二分循环查找
				high = mid - 1;
			}
		}
		return -1;//在这个函数中,如果有异常就返回-1,即 return -1; 
		//这是一种编程技巧,如果出现异常就通过返回-1就知道该函数出现异常
}

算法三:threeSumTwoPointer()

分析:将数组排序,然后通过双指针进行查找,从数组两侧往中间进行查找,时间复杂度为O(N2)。

解题思路

  • 将数组元素进行sort()函数排序;
  • 数组两侧相加,从中间元素这种查找与两侧相加的值相等的第三个元素;
public class threeSumTwoPointer implements ThreeSum {
	public int count(int[], nums) {
		int N = nums.length;
		int cnt = 0;
		Arrays.sort(nums);\\通过Arrays.sort()函数将数组nums进行排序
		for (int i = 0; i < N - 2; i++) {
		//将nums[0]的相反数赋给target
		//num[low]、nums[high]分别初始化为数组第二个和最后一个元素
			int low = i + 1, high = N - 1, target = -num[i];
			while (low < high) {
				int sum = nums[low] + nums[high];//两元素相加赋给sum
				//if else判断sum 和 target 的大小关系,即三元素之和是否为0
				if (sum == target) {
				cnt++;
				low++;
				high--;
				} else if (sum < target) {
				low++;
				} else {
					high--;
				}
			}
		}
		return cnt;
	}
}

注释:写的不好之处请您纠正,新手小白,期待您来指教!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值