时间复杂度
时间复杂度算的不是时间而是算法执行次数,用O()渐进表示法表示
1、当M和N不知道大谁小的时候,都要考虑到
//时间复杂度为O(M+N)
void Func3(int N,int M)
{
int count = 0;
for(int k = 0; k < M; ++k)
{
++count;
}
for(int k = 0; k < N; ++k)
{
++count;
}
printf("%d\n",count);
}
2、当算法存在最好、最坏、平均这三种情况的时候,我们要算最坏的情况
//时间复杂度为O(N)
const char* strchr(const char* str, char character)
{
while(*str != '\0')
{
if(*str == character)
return str;
++str;
}
return NULL;
}
3、冒泡排序实现:第一趟冒泡排序数是N、第二趟冒泡排序数是N-1、
第三趟冒泡排序数是N-3、......、第N-1趟冒泡数是2、第N趟冒泡数是1,等差数列(N+1)*N/2
//时间复杂度为O(N^2)
void BubbleSort(int* a, int n)
{
assert(a);
for(size_t end = n; end > 0; --end)
{
int exchange = 0;
for(size_t i = 1; i < end; ++i)
{
if(a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
}
if(exchange == 0)
break;
}
4、二分查找、找了1次是1、找了2次是2、找了3次是4、找了4次是8,因为是考虑最坏的情况,所以1*2*2*2=N,2^x=N——>X=logN
//时间复杂度为O(logN) 以2为底,写不出来
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n;
while(begin < end)
{
int mid = begin + ((end - begin)>>1);
if(a[mid] < x)
begin = mid + 1;
else if(a[mid] > x)
end = mid;
else
return mid;
}
return -1;
}
5、递归调用了N次,时间复杂度为O(N)
//阶乘递归的时间复杂度为O(N)
long long Factorial(size_t N)
{
return N < 2 ? N : Factorial(N-1)*N;
}
空间复杂度
空间复杂度算的不是空间而是变量的个数
1、时间是累计的,空间是不累计的
//时间复杂度是O(1)
void BubbleSort(int* a,int n)
{
assert(a);
for(size_t end = n; end > 0; --end)
{
int exchange = 0;
for(size_t i = 1; i < end; ++i)
{
if(a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if(exchange == 0)
break;
}
}
2、计算的是影响结果最大的那一项
//空间复杂度是O(N)
long long* Fibonacci(size_t n)
{
if(n==0)
return NULL;
long long* fibArray = (long long*)malloc((n+1)*sizeof(long long));
fibArray[0] = 0;
fibArray[1] = 1;
for(int i = 2; i <= n; ++i)
{
fibArray[i ] = fibArray[ i - 1] + fibArray[i - 2]
}
return fibArray;
}
3、计算累积变量最多的,最终都会被销毁
//空间复杂度是O(N)
long long Factorial(size_t N)
{
return N < 2 ? N : Factorial(N-1)*N;
}
练习
1、数组中缺失了一个数,请找出缺失的数,你能在时间复杂度O(N)内完成吗
思路:异或——>用0~N的数和数组的数异或,剩下的数就是缺失的
int missingNumber(int* nums, int numsSize)
{
int x = 0;
for(int i = 0; i < numsSize; ++i)
{
x ^= nums[i];
}
for(int j = 0; j < numsSize+1; ++j)
{
x ^= j;
}
return x;
}
2、旋转数组,给定一个数组,将数组中的元素向右移动k个位置,其中k是非负数,你能在空间复杂度O(1)内完成吗
思路:后k个逆置,前n-k个逆置,再整体逆置
void Reverse(int* nums, int left, int right)
{
while(left < right)
{
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
++left;
--right;
}
}
void rotate(int* nums, int numsSize, int k)
{
if(k >= numsSize)
{
k %= numsSize;
}
Reverse(nums, numsSize-k,numsSize-1);
Reverse(nums, 0, numsSize-k-1);
Reverse(nums, 0, numsSize-1);
}