(叠甲:如有侵权请联系,内容都是自己学习的总结,一定不全面,仅当互相交流(轻点骂)我也只是站在巨人肩膀上的一个小卡拉米,已老实,求放过)
时间复杂度:时间复杂度是指算法中基本操作的执行次数随输入规模 n 增长的渐近趋势。它不关心算法在特定硬件上的实际运行秒数(受 CPU、编程语言、编译器等影响),只关注算法本身的效率随数据量变大的增长规律。
空间复杂度:空间复杂度是指算法在运行过程中所需的额外内存空间随输入规模 n 增长的渐近趋势。
题一:数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
题目分析:该题实测了两种解题思路
第一种:使用计数排序的思路从而找出缺失的数,但这样的空间复杂度是O(N),因为要遍历数组,时间复杂度也是O(N);
cpp
int missingNumber(int* nums, int numsSize)
{
int* a = malloc(sizeof(int)*(numsSize+1));
//这里不要使用int a[numsize+1] = {0}的变长数组,只有少数编译器支持;
memset(a,0,sizeof(int)*(numsSize+1));
//这一步非常关键,如果没有初始化数组的话,可能会有些脏数据影响输出;
for(int i = 0;i<numsSize;i++)
{
a[nums[i]]++;
}
for(int j = 0;j<=numsSize;j++)
{
if(!a[j])
{
free(a);
return j;
}
}
free(a);
return -1;
}
第二种:遍历数组求和,再依次减去原数组的值,这种方法的时间复杂度依旧是O(N),但是空间复杂度却来到了O(1);
cpp
int missingNumber(int* nums, int numsSize)
{
int sum = 0;
for(int i = 0;i<=numsSize;i++)
{
sum = sum +i;
}
for(int j = 0;j<numsSize;j++)
{
sum = sum-nums[j];
}
return sum;
}
题目二:整数数组 sockets 记录了一个袜子礼盒的颜色分布情况,其中 sockets[i] 表示该袜子的颜色编号。礼盒中除了一款撞色搭配的袜子,每种颜色的袜子均有两只。请设计一个程序,在时间复杂度 O(n),空间复杂度O(1) 内找到这双撞色搭配袜子的两个颜色编号。
题目分析:该题要求空间复杂度为O(1),计数排序就行不通了,使用位运算的异或运算以及与运算比较合适;首先将数组的数据全部进行异或(^)操作,得到一个值a,再将该值与取负(原码取反+1),得到(-a),将a与(-a)进行与(&)运算得到key值,key值就意味着该组数据中可以从右往左边数第几位为1,在使用key值作为分组的桥梁,是的同一组内的不同值再进行一次异或(^)操作,最后留下来的数就是需要的答案了;
cpp
int* sockCollocation(int* sockets, int socketsSize, int* returnSize)
{
int a = 0;
//用于存放最初的异或值
for(int i =0;i<socketsSize;i++)
{
a = a^sockets[i];
}
int key = a&(-a);
//计算key值桥梁
int num1 = 0;
int num2 = 0;
for(int j = 0;j<socketsSize;j++)
{
if(sockets[j]&key)
//进行分组
{
num1 = num1^sockets[j];
}
else
{
num2 = num2^sockets[j];
}
}
int* result = malloc(2*sizeof(int));
//开辟存储结果的数组;
result[0] = num1;
result[1] = num2;
*returnSize = 2;
//确认结果数组的长度
return result;
}
注意:函数头部的int* returnSize是一个整数,而且是返回数组的长度,并不是一个数组。