IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C语言力扣第十五题之三数之和。三指针法 -> 正文阅读

[数据结构与算法]C语言力扣第十五题之三数之和。三指针法

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。


示例 1:

输入:nums = [-1, 0, 1, 2, -1, -4]
输出:[[-1, -1, 2], [-1, 0, 1]]

示例 2:

输入:nums = []
输出:[]

示例 3:

输入:nums = [0]
输出:[]


提示:

0 <= nums.length <= 3000
- 105 <= nums[i] <= 105

来源:力扣(LeetCode)
链接:https ://leetcode.cn/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

*返回大小为*returnSize的数组。

*数组的大小作为*returnColumnSizes数组返回。

*注意:返回的数组和*columnSizes数组都必须是malloced,假设调用方调用free()。


1: 快速排序,之后使用双指针遍历对应的位置,求解
2: 主要是在确定了第一个值,后通过双指针的方式,确定出来其余两个值
3: 将结果统计出来

nums = [-1,0,1,2,-1,-4]
快排结果如下:
nums = [    -4,     -1,     -1,     0,      1,      2]
三指针       ^        ^                             ^
             |        |                             |
            Left    Middle                      indexRight
初始状态              |
                     遍历 middle 和 indexRight的区间
Left + Middle + indexRight = -4  + -1 + 2  = -3 < 0
Middle移动 一直移动    Middle == -1 , 0 , 1 < 0 
Left = -4的没有符合的
************************
移动 Left
nums = [    -4,     -1,     -1,     0,      1,      2]
                     ^       ^                      ^       
                     |       |                      |
                    Left    Middle                indexRight   
Left + Middle + indexRight = -1  + -1 + 2  = 0 记录结果
************************
移动Middle 
nums = [    -4,     -1,     -1,     0,      1,      2]
                     ^              ^               ^       
                     |              |               |
                    Left            Middle        indexRight 
  Left + Middle + indexRight = -1  + 0 + 2  > 0 不符合
************************
indexRight 
nums = [    -4,     -1,     -1,     0,      1,      2]
                     ^              ^       ^       
                     |              |       |
                    Left            Middle indexRight 
  Left + Middle + indexRight = -1  + 0 + 1  = 0 符合
此时Left等于-1时的结果遍历结束。
************************
移动 Left
nums = [    -4,     -1,     -1,     0,      1,      2]
                             ^        
                             |      
                            Left     
Left和一个Left值一样,会得到相同的结果不符合
************************
移动 Left
nums = [    -4,     -1,     -1,     0,      1,      2]
                                    ^        
                                    |      
                                    Left    
开始遍历只有1种可能 0, 1 ,2 不符合
************************
移动 Left
nums = [    -4,     -1,     -1,     0,      1,      2]
                                            ^        
                                            |      
                                            Left    
Left的值 大于 0了,因为Left是最小的,所以不能三个数相加等于0
直接退出返回
************************
int cmp(const void *a, const void *b)
{
	return *(int*)a - *(int*)b;
}

int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{
	*returnSize = 0;
	if (numsSize < 3)
		return NULL;
	qsort(nums, numsSize, sizeof(int), cmp);
	int **ans = (int **)malloc(sizeof(int *) * numsSize  *numsSize);
	*returnColumnSizes = (int *)malloc(sizeof(int) * numsSize * numsSize);
	int i, j, k, sum;

	int indexLeft = 0;
	int indexMiddle = 0;
	int indexRight = 0;
	//快排过后,使用三指针 遍历
	//左边遍历到倒数第三位即可
	for (indexLeft = 0; indexLeft < numsSize - 2; indexLeft++)
	{
		if (nums[indexLeft] > 0)
		{
			//因为是快排的结果,所以如果出现大零的
			//后面的值都是大于0的
			return ans;
		}

		//如果值相同 则不需要遍历
		if (indexLeft > 0 && nums[indexLeft] == nums[indexLeft - 1])
			continue;
		indexMiddle = indexLeft + 1;
		indexRight = numsSize - 1;

		//双指遍历 找到所有的可能
		while (indexMiddle < indexRight)
		{
			sum = nums[indexLeft] + nums[indexMiddle] + nums[indexRight];

			if (sum == 0)
			{
				ans[*returnSize] = (int*)malloc(sizeof(int) * 3);
				(*returnColumnSizes)[*returnSize] = 3;
				ans[*returnSize][0] = nums[indexLeft];
				ans[*returnSize][1] = nums[indexMiddle];
				ans[*returnSize][2] = nums[indexRight];
				*returnSize += 1;
				//过滤相等的值
				while (indexMiddle < indexRight && nums[indexMiddle] == nums[++indexMiddle]);
				while (indexMiddle < indexRight && nums[indexRight] == nums[--indexRight]);
			}
			else if (sum > 0)
			{
				//左边递减
				indexRight--;
			}
			else
			{
				//右边递增
				indexMiddle++;
			}
		}
	}
	return ans;
}


int main()
{
	int nums[6] = { -1, 0, 1, 2, -1, -4 };
	int numsSize = 6;
	int i = 0, j = 0;
	int returnSize;// 表示返回的二维数组的行数
	int **returnColumnSize;// 指向列数组指针的指针
	// 注意:列数组在哪我们无从得知,也不需要知道,
	// 我们只要知道有个一阶指针指向它就行了,我把它叫做列数组指针
	int **ans = threeSum(nums, numsSize, &returnSize, returnColumnSizes);
	// &returnSize 引用传值
	// 最后一个参数我认为也可以是 int *returnColumnSize,然后传入&returnColumnSizes,效果是一样的
	for (i = 0; i < (*returnSize); i++) {
		for (j = 0; j < (*returnColumnSize)[i]; j++)
			printf("%d", ans[i][j]);
		printf("\n");
	}
	return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:13:18  更:2022-07-04 23:13:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:23:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码