「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。
前言
一个程序,有一种书本上的描述:解决一个问题除了要有一个数据结构来表示和组织信息外,还需要一系列步骤来完成问题的解决方案。
当然了,第一个逗号前面的那当然就是数据结构了,那后面的一系列步骤其实说的就是算法。
也可以称为:操作数据结构的方法;或者称为:解决问题的方案。
我学算法的目的
因为我想在找工作的时候更有竞争力,更有话语权,所以我来学算法!
一、题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/3s…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
实例:
输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
输入: nums = []
输出: []
提示:
-
0 <= nums.length <= 3000
-
-105 <= nums[i] <= 105
-
0 <= nums.length <= 3000
-
-105 <= nums[i] <= 105
二、题目解析
- 空数组/元素数目小于3返回空
- 排序原数组
- 遍历排序后的数组
- 使用二分法找到三数之和 细节处理:
- 当前数组大于0,表示后续没有三数之和为0,结束遍历
- 当前元素与上一次相等,跳过此次计算,去重 什么是二分法: 二分查找法是一种算法
他经常用在:
给定一个升序的数组/列表和一个目标值,尽可能快的查找其中的目标值
若存在,返回目标值得索引
若不存在,返回-1
这样的场景
因为是升序的,所以我们可以以数组中间的元素为中线,将数组分为左右两个数组
三、代码讲解
/**
* 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().
*/
/*
- 空数组/元素数目小于3返回空
- 排序原数组
- 遍历排序后的数组
- 使用二分法找到三数之和
细节处理:
- 当前数组大于0,表示后续没有三数之和为0,结束遍历
- 当前元素与上一次相等,跳过此次计算,去重
*/
// qsort的比较函数
int cmp(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
// 先记录返回的行数为0
*returnSize = 0;
// 输入为空、或元素个数小于3则返回NULL
if (nums == NULL || numsSize < 3) {
return NULL;
}
// 将nums排序为升序排列
qsort(nums, numsSize, sizeof(int), cmp);
// 分配返回数组、返回数组的列数
int** ret = (int**)malloc(numsSize * numsSize * sizeof(int*));
*returnColumnSizes = (int*)malloc(numsSize * numsSize *sizeof(int));
// 排序后的数组从头到尾进行遍历
for (int i = 0; i < numsSize; i++) {
// 当前数组大于0,表示后续没有三数之和为0,结束遍历
if (nums[i] > 0) {
break;
}
// 当前元素与上一次相等,跳过此次计算,去重
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
// 定义左右指针
int left = i + 1, right = numsSize - 1;
// 开始查找三数之和为0
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0) {
ret[*returnSize] = (int*)malloc(sizeof(int) * 3);
ret[*returnSize][0] = nums[i];
ret[*returnSize][1] = nums[left];
ret[*returnSize][2] = nums[right];
// 返回数组当前行的列数为3
(*returnColumnSizes)[*returnSize] = 3;
// 返回数组的行数自加1
(*returnSize)++;
// 对左右指针进行去重
while (left < right && nums[left] == nums[++left]);
while (left < right && nums[right] == nums[--right]);
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return ret;
}
结语
算法的出现也是因为有了问题,之前也说过算法是什么了,就是一个问题的解决方案,所以我们的算法是为了解决问题才出现的。
当然,主要还是为了money,刷算法,冲大厂,加油。
成功不难,就在于你是否会比别人更会吃苦。