leetcode题目-3数 之和

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

思路如下:

  1. 先用快排将数组排序;
  2. 在遍历数组,选择数a;
  3. 两个指针i,j从剩下的数组中分别从最左边和最右边开始遍历,其中b=nums[i],c=nums[j],找到a+b+c=0的记录下来;
  4. 当i<j条件不成立时,退出内层循环,i++;
  5. 注意不重复条件,当a与上一次a值相同时,本次外层循环不用进行,i++;
    当a,b,c与前一次完全相同时,本次内层循环无效。

代码

C版

/**
 * Return an array of arrays of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
 //先将数字排序
void quickSort(int a[], int left, int right) {
	if (left >= right)
		return;
	//枢纽单元的选取为最左边、最中间、最右边三个数的中位数,使得左右分布尽量均匀
	int key;
	int index = 0;
	if (a[left] > a[right] && a[left] < a[(left + right) / 2] || a[left]<a[right] && a[left] > a[(left + right) / 2]) {
		key = a[left];
		index = left;
	}
	else if (a[right] > a[left] && a[right] < a[(left + right) / 2] || a[right]<a[left] && a[right] > a[(left + right) / 2]) {
		key = a[right];
		index = right;
	}
	else {
		key = a[(left + right) / 2];
		index = (left + right) / 2;
	}
	//将key的值放在第一位
	int temp = a[left];
	a[left] = a[index];
	a[index] = temp;

	//实现大数右边小数左边
	int i = left, j = right;
	while (i < j) {
		while (i<j&&a[j]>key) { j--; }
		if (i < j) {
			a[i++] = a[j];
		}
		while (i < j&&a[i] < key) { i++; }
		if (i < j) {
			a[j--] = a[i];
		}
	}
	//最后退出一定是i==j,因为某个(i或者j)在等待时,另一个++或--,当++或--到与另一个相等时
	//就退出,这时相等的下标位置就是等待着插入元素的位置,也就是最后要放key值的位置。
	a[i] = key;
	//递归地处理左边,递归地处理右边
	quickSort(a, left, i - 1);
	quickSort(a, i + 1, right);

}

int** threeSum(int* nums, int numsSize, int* returnSize) {
	//快排
	quickSort(nums, 0, numsSize - 1);
	//定元素a,然后用双指针从两边开始找
	//先用最多个数数组考虑
	int maxLength = numsSize/3 ;
	int length = 0;
	int **a = (int**)malloc(sizeof(int*)*maxLength);
	for (int i = 0; i < maxLength; i++) {
		a[i] = (int*)malloc(sizeof(int) * 3);
	}
	int i = 0, j, k;
	int la=0x7fffffff, lb= 0x7fffffff, lc= 0x7fffffff;//由于数组是有序的,因此重复的元组必定是连续的
	while (i < numsSize - 2) {
		j = i + 1;
		k = numsSize - 1;
		if (la == nums[i]) {
			i++;
			continue;
		}
		while (j < k) {
			if (nums[i] + nums[j] + nums[k] == 0) {
				if (!(nums[j] == lb && nums[k] == lc)) {
					if (length > maxLength-1) {
						int * temp = (int*)malloc(sizeof(int) * 3);
						temp[0] = nums[i];
						temp[1] = lb = nums[j];
						temp[2] = lc = nums[k];
						a = (int**)realloc(a,(++length)*sizeof(int*));
						a[length - 1] = temp;
					}
					else {
						a[length][0] = nums[i];
						a[length][1] = lb = nums[j];
						a[length][2] = lc = nums[k];
						length++;
					}
					
				}
				j++;
				k--;
			}
			else if (nums[i] + nums[j] + nums[k] > 0) {
				k--;
			}
			else if (nums[i] + nums[j] + nums[k] < 0) {
				j++;
			}
		}
		la = nums[i];
		i++;
	}
	*returnSize = length;
	return a;
}

4个数字的代码(经过整理比3个数字的更清晰,3个数字的出现了数组越界访问的问题,但vs没报错)

int** fourSum(int* nums, int numsSize, int target, int* returnSize) {
	for (int i = 0; i < numsSize - 1; i++) {
		for (int j = i + 1; j < numsSize; j++) {
			if (nums[i] > nums[j]) {
				int temp = nums[i];
				nums[i] = nums[j];
				nums[j] = temp;
			}
		}
	}
	int **a = (int**)malloc(sizeof(int*)*numsSize);
	int outputSize = 0, maxSize = numsSize, incre = numsSize / 4;
	for (int i = 0; i < maxSize; i++) {
		a[i] = (int*)malloc(sizeof(int) * 4);
	}
	for (int i = 0; i < numsSize - 3; i++) {
		if (i == 0 || nums[i] > nums[i - 1]) {
			for (int j = i + 1; j < numsSize - 2; j++) {
				if (j == i + 1 || nums[j] > nums[j - 1]) {
					int m = j + 1, n = numsSize - 1;
					while (m < n) {
						if (nums[i] + nums[j] + nums[m] + nums[n] == target) {
							if (outputSize >= maxSize) {
								maxSize += incre;
								a = (int**)realloc(a, sizeof(int*)*(maxSize));
								for (int t = outputSize; t < outputSize + incre; t++) {
									a[t] = (int*)malloc(sizeof(int) * 4);
								}
							}
							a[outputSize][0] = nums[i];
							a[outputSize][1] = nums[j];
							a[outputSize][2] = nums[m];
							a[outputSize][3] = nums[n];
							outputSize++;
							m++;
							n--;
							while (m<numsSize&&nums[m] == nums[m - 1]) { m++; }
							while (n>-1&&nums[n] == nums[n + 1]) { n--; }
						}
						else if (nums[i] + nums[j] + nums[m] + nums[n] < target) {
							m++;
							while (m < numsSize&&nums[m] == nums[m - 1]) { m++; }
						}
						else if (nums[i] + nums[j] + nums[m] + nums[n] > target) {
							n--;
							while (n > -1 && nums[n] == nums[n + 1]) { n--; }
						}
					}
				}
			}
		}
	}
	*returnSize = outputSize;
	return a;
}

python 版

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        res =[]
        i = 0
        for i in range(len(nums)):
            if i == 0 or nums[i]>nums[i-1]:
                l = i+1
                r = len(nums)-1
                while l < r:
                    s = nums[i] + nums[l] +nums[r]
                    if s ==0:
                        res.append([nums[i],nums[l],nums[r]])
                        l +=1
                        r -=1
                        while l < r and nums[l] == nums[l-1]:
                            l += 1
                        while r > l and nums[r] == nums[r+1]:
                            r -= 1
                    elif s>0:
                        r -=1
                    else :
                        l +=1
        return res

猜你喜欢

转载自blog.csdn.net/qq_40836518/article/details/89210561
今日推荐