一. 简介
本文记录力扣网上的逻辑编程题,涉及数组方面的,这里记录一下 C语言实现和Python实现。
二. 力扣网C语言编程题:三数之和
题目:三数之和
给你一个整数数组 nums ,判断是否存在三元组 nums\[i, numsj, numsk] 满足 i != j、i != k 且 j != k ,同时还满足 numsi + numsj + numsk == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = -1,0,1,2,-1,-4
输出:\[-1,-1,2,-1,0,1]
解释:
nums0 + nums1 + nums2 = (-1) + 0 + 1 = 0 。
nums1 + nums2 + nums4 = 0 + 1 + (-1) = 0 。
nums0 + nums3 + nums4 = (-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 <= numsi <= 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语言有区别。好像写起来也没想象中困难,加油!