一. 简介
本文记录力扣网上的逻辑编程题,涉及数组方面的,这里记录一下 C语言实现和Python实现。
二. 力扣网C语言编程题:三数之和
题目:三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
解题思路:
根据题目要求,数组中找到三个元素之和为0,且不重复的三元组。这里解决不重复的方法就是排序,排序后查重就可以保证不重复。
固定一个元素,使用双指针,从数组的头部与尾部进行同时进行查找,查找第二元素和第三个元素。
具体方法:
-
从小到大进行排序;
-
遍历数组,元素去重;
-
开始从数组首部和尾部开始同时进行,统计三个元素为 0的元素,如果和小于0,则移动左指针。如果大于0则移动右指针。如果等于0则保存数据,然后对左边指针的元素进行查重,右边指针的元素进行查重;
C语言实现如下:
#include <stdio.h>
//从小到大排序
int compare_data(const void* a, const void* b) {
return *(int*)a -*(int*)b;
}
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
if((nums == NULL) || (numsSize <= 0) || (returnSize == NULL) || (returnColumnSizes == NULL)) {
return NULL;
}
*returnSize = 0;
int left = 0;
int right = 0;
int i = 0;
//分配返回数组的缓存
int** ret_data = (int**)malloc(10*numsSize * sizeof(int*));
*returnColumnSizes = (int*)malloc(10*numsSize * sizeof(int));
//从小到大排序
qsort(nums, numsSize, sizeof(int), compare_data);
//遍历数组(从头部和尾部同时)
for(i = 0; i < (numsSize-2); i++) {
//当前元素大于0,那么更不可能存在sum值等于0的数了,结束遍历
if(nums[i] > 0) {
break;
}
//元素去重(当前元素与上一次元素相等,跳过此次计算)
if(i > 0 && nums[i] == nums[i-1]) {
continue;
}
left = i+1;
right = numsSize-1;
//开始查找三数之和
while(left < right) {
//判断和的值
int sum = nums[i] + nums[left] + nums[right];
if(sum == 0) {
//分配内存,保存结果
ret_data[*returnSize] = (int*)malloc(3 * sizeof(int));
ret_data[*returnSize][0] = nums[i];
ret_data[*returnSize][1] = nums[left];
ret_data[*returnSize][2] = nums[right];
(*returnColumnSizes)[*returnSize] = 3; //返回数组当前行的列数为3
(*returnSize)++; //三元组的个数
//左边指针的元素进行查重
while((left < right) && (nums[left] == nums[++left]));
//右边指针的元素进行查重
while((left < right) && (nums[right] == nums[--right]));
}
else if(sum < 0) { //左指针向右移找大值
left++;
}
else { //右指针向左移找小值
right--;
}
}
}
return ret_data;
}
Python实现如下:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
ret = []
n = len(nums)
#从小到大进行排序,方便去重
nums.sort()
#遍历数组元素(从数组的首部和尾部同时进行)
#0 ~ n-3
for i in range(0, n-2):
#如果第一个元素大于0,则不必查找了(后面元素更大)
if(nums[i] > 0):
break
#元素查重(如果当前元素与上一次元素相等,则跳过这次计算)
if(i > 0 and nums[i] == nums[i-1]):
continue
left = i + 1
right = n - 1
#查找和为0的三元组
while(left < right):
sum = nums[i] + nums[left] + nums[right]
#和 == 0
if(sum == 0):
ret.append([nums[i], nums[left], nums[right]])
#左右指针的元素查重
while(left < right and nums[left] == nums[left+1]):
left += 1
while(left < right and nums[right] == nums[right-1]):
right -= 1
left += 1
right -= 1
#和 < 0,则左指针向右移(说明和小了,需要和增大)
elif(sum < 0):
left += 1
#和 > 0,则右指针向左移(说明和大了,需要和减小)
else:
right -= 1
return ret
第一次写 Python,是与 C语言有区别。好像写起来也没想象中困难,加油!