1282、用户分组

题目描述:

有 n 位用户参加活动,他们的 ID 从 0 到 n - 1,每位用户都 恰好 属于某一用户组。给你一个长度为 n 的数组 groupSizes,其中包含每位用户所处的用户组的大小,请你返回用户分组情况(存在的用户组以及每个组中用户的 ID)。

你可以任何顺序返回解决方案,ID 的顺序也不受限制。此外,题目给出的数据保证至少存在一种解决方案。

 

示例 1:

输入:groupSizes = [3,3,3,3,3,1,3]
输出:[[5],[0,1,2],[3,4,6]]
解释: 
其他可能的解决方案有 [[2,1,6],[5],[0,4,3]] 和 [[5],[0,6,2],[4,3,1]]。
示例 2:

输入:groupSizes = [2,1,3,3,3,2]
输出:[[1],[0,5],[2,3,4]]
 

提示:

groupSizes.length == n
1 <= n <= 500
1 <= groupSizes[i] <= n

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/group-the-people-given-the-group-size-they-belong-to
 

解题思路:

  1. 一开始是冲着贪心的标签做这题的,不知道是我太菜了还是怎么回事,觉得这题和贪心似乎关系不大?
  2. 数据数量有限,就直接做分类了,对所有的“所处用户组数量大小相同”的数据,记录其下标,并且分别记录每个用户组数量下的数据总数(有点绕口,比如说某几个数据,其所处用户组大小为3,记录这几个数据的总数),之后就对做好分类的数据做处理就可以了;
  3. 把已经分好类的数据以此填充到返回数组中即可。

 

个人疑虑:

  1. 一开始没有用题目给出的最大范围来开辟数组空间,想节省内存。在数据分类、将分类完的数据填充到返回数组时,使用了大量的realloc。使用原因:如果直接用最大范围开辟数组空间,会有一部分的空间没有被使用到,造成空间浪费,就想着确定要用了,然后再去开辟,结果时间和空间耗用都不尽如人意。
    下面的第一段代码空间占用大概在11.7M,时间从40~50ms都有,第二段代码的代码空间占用达到了24.5M,时间达到了64ms,具体原因和realloc的机制应该有关系,解决之后再来填补。

代码一,时间、内存都还算可以的代码

int** groupThePeople(int* groupSizes, int groupSizesSize, int* returnSize, int** returnColumnSizes)
{
	int group_array[500][500] = { 0 };		//第一维:用户组长度
											//第二维:

	int *group_length = (int*)calloc(groupSizesSize, sizeof(int));	

	short i;						
	short k = 0;
	for (i = 0; i < groupSizesSize; i++)
	{
		k = groupSizes[i] - 1;					//

		if (k < 0 || k >= 500)
			continue;

		group_array[k][group_length[k]] = i;	//将当前下标数据存到相应数组

		group_length[k]++;						//当前长度的用户组数量+1
	}

	int** ret_res = (int*)malloc(sizeof(int*)*groupSizesSize);	//暂时所有长度,包含无用长度
	(*returnColumnSizes) = (int*)malloc(sizeof(int)*groupSizesSize);

	*returnSize = 0;		//清零

	int n;

	for (i = 0; i < groupSizesSize; i++)		//所有用户组长度进行遍历
	{
		n = 0;									//

		while (group_length[i] > 0)			//当前数组长度仍然大于0,即没有全部分类完成
		{
			(*returnColumnSizes)[*returnSize] = i + 1;		//指示当前一维数组的长度


			ret_res[*returnSize] = (int*)malloc(sizeof(int)*(i + 1));	//当前数组有i+1个int数据 

			for (k = 0; k <= i; k++)		//i 是用户组数-1  所以要加上等号
			{
				ret_res[*returnSize][k] = group_array[i][n];

				n++;
				group_length[i]--;
			}

			*returnSize += 1;
		}

	}

	return ret_res;

}

 

第二段代码,时间、内存占用都很高的代码

int** groupThePeople(int* groupSizes, int groupSizesSize, int* returnSize, int** returnColumnSizes)
{
	int group_array[500][500] = { 0 };		//第一维:用户组长度
											//第二维:

	int *group_length = (int*)calloc(groupSizesSize, sizeof(int));	

	short i;				
	short k = 0;
	for (i = 0; i < groupSizesSize; i++)
	{
		k = groupSizes[i] - 1;					//

		if (k < 0 || k >= 500)
			continue;

		group_array[k][group_length[k]] = i;	//将当前下标数据存到相应数组

		group_length[k]++;						//当前长度的用户组数量+1
	}

	int** ret_res = NULL;
	(*returnColumnSizes) = (int*)malloc(sizeof(int)*groupSizesSize);

	*returnSize = 0;		//清零

	int n;

	for (i = 0; i < groupSizesSize; i++)		//所有用户组长度进行遍历
	{
		n = 0;									//

		while (group_length[i] > 0)			//当前数组长度仍然大于0,即没有全部分类完成
		{
			//(*returnColumnSizes) = (int*)realloc(*returnColumnSizes, sizeof(int)*(*returnSize + 1));
			(*returnColumnSizes)[*returnSize] = i + 1;		//指示当前一维数组的长度

			//需要的时候再把返回数组延长
			ret_res = (int*)realloc(ret_res, sizeof(int*)*(*returnSize + 1));
			ret_res[*returnSize] = (int*)malloc(sizeof(int)*(i + 1));	//当前数组有i+1个int数据 

			for (k = 0; k <= i; k++)		//i 是用户组数-1  所以要加上等号
			{
				ret_res[*returnSize][k] = group_array[i][n];

				n++;
				group_length[i]--;
			}

			*returnSize += 1;
		}

	}

	return ret_res;

}

 

以下属于菜鸟的知识点总结,是知识漏洞,之前没有细看过。

  1. 之前没有在实际项目中使用二级指针做形参过,这个函数中形参int** returnColumnSizes,一开始以为是传了一个二维数组进去,我在VS中直接int** return_column_sizes,然后调用函数的时候报错。
    后来才搞明白其实就是传了个一维数组进去,只不过传的不是一维数组的起始地址,而是传了一个指向这个地址的指针。
    举个例子,定义了一个数组 int array[100],如果直接使用 array,array的值就是array[100]这个数组的起始地址;&array,就是array的地址,这个地址中存的数据是array[100]这个数组的起始地址。
    函数中,int** returnColumnSizes 这个形参的位置,就应该放 &array,那么函数中 *returnColumnSizes  = array,两者都是数组的起始地址,(*returnColumnSizes)[10] = array[10],两者都是这个数组的第十个元素(此处=符号仅代表等价)。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值