leetcode:汇总区间(详解)

前言:内容包括:题目,代码实现,大致思路,代码解读

目录

题目:

代码实现:

大致思路:

代码解读:

part 1

part 2


题目:

给定一个  无重复元素 的 有序 整数数组 nums 。

返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字 x 。

列表中的每个区间范围 [a,b] 应该按如下格式输出:

"a->b" ,如果 a != b
"a" ,如果 a == b
 

示例 1:

输入:nums = [0,1,2,4,5,7]
输出:["0->2","4->5","7"]
解释:区间范围是:
[0,2] --> "0->2"
[4,5] --> "4->5"
[7,7] --> "7"
示例 2:

输入:nums = [0,2,3,4,6,8,9]
输出:["0","2->4","6","8->9"]
解释:区间范围是:
[0,0] --> "0"
[2,4] --> "2->4"
[6,6] --> "6"
[8,9] --> "8->9"
 

提示:

0 <= nums.length <= 20
-231 <= nums[i] <= 231 - 1
nums 中的所有值都 互不相同
nums 按升序排列

代码实现:


char** summaryRanges(int* nums, int numsSize, int* returnSize)
{
	char** ret = (char**)calloc(numsSize, sizeof(char*));

	int i = 0;
	for (i = 0; i < numsSize; i++)
	{
		ret[i] = (char*)calloc(25, sizeof(char));
	}

	int left = 0;
	int index = 0;
	for (i = 0; i < numsSize; i++)
	{
		left = i;
		while (i < numsSize - 1 && nums[i] + 1 == nums[i + 1])
		{
			i++;
		}

		if (left == i)
		{
			sprintf(ret[index++], "%d", nums[i]);
		}
		else
		{
			sprintf(ret[index++], "%d->%d", nums[left], nums[i]);
		}
	}
	*returnSize = index;
	return ret;
}

大致思路:

区间的划分:连续的数字成为一个区间

比如:0,1,2,4,5,7

区间的划分为:0~2    4~5   7

1 遍历整个数组: 每次先用left存储左区间数字的下标,当满足前一个元素(下标是i)+1 = 后一个元素(下标是i+1)时,不断跳过这个下标为i的元素,当不满足条件结束循环时,i就是右区间的下标

若是区间仅有1个数值(left==i)即区间的左边界值的下标和右边界值的下标相等,则直接将此数值转成字符串即可

若是区间的数值>1,则将一个区间左边界上的数值(left为其下标)和右边界上的数值(i为其下标)按照:数值->数值  的形式转成字符串

下面介绍一个能将数据转成字符串形式的函数:sprintf 将格式化数据写入字符串

 语法:

int sprintf ( char * str, const char * format, ... );

终止空字符会自动追加到内容之后

代码解读:

part 1

    char** ret = (char**)calloc(numsSize, sizeof(char*));

	int i = 0;
	for (i = 0; i < numsSize; i++)
	{
		ret[i] = (char*)calloc(25, sizeof(char));
	}

calloc开辟一块numsSize大小的空间,每个空间的元素类型是char*类型,即字符数组的数组名

为开辟好的numsSize个空间存入一个字符数组的数组名,代表着一个字符串的首元素的地址

这个字符串的大小需要足够大,我们注意到nums[i] <= 2^31-1

即nums中的数字最大是10位数,添上负号存入字符数组中可以算作11个字符,不要忘记字符数组中要有一个位置留给sprintf自动追加的'\0'哦!

part 2

    int left = 0;
	int index = 0;
	for (i = 0; i < numsSize; i++)
	{
		left = i;
		while (i < numsSize - 1 && nums[i] + 1 == nums[i + 1])
		{
			i++;
		}

		if (left == i)//区间中只有一个数字
		{
			sprintf(ret[index++], "%d", nums[i]);//将数字写入字符数组中
		}
		else
		{
			sprintf(ret[index++], "%d->%d", nums[left], nums[i]);
		}
	}
	*returnSize = index;
	return ret;

遍历整个数组:

left存入一个区间左边界数值的下标

当下标为i的元素+1 = 下标为i+1的元素时,不断跳过这个元素

注意:

1   需要注意访问越界的问题,i只要遍历到数组倒数第二个元素的位置就好,因为倒数第二个元素的后一个元素就是数组的最后一个元素,若是i遍历到数组最后一个元素的位置,则i+1的位置不是数组的空间,属于非法访问

所以i

while (i < numsSize - 1 && nums[i] + 1 == nums[i + 1])

条件不能颠倒位置,若是:

while (nums[i] + 1 == nums[i + 1] && i < numsSize - 1 )

会出现:在已经访问越界的情况下去判断是否越界

所以我们要防患于未然,先判断访问是否越界

你可能感兴趣的:(leetcode,leetcode)