3. 空間の複雑さ
スペースの複雑さは数式でもあり、動作中にアルゴリズムが一時的に占有するストレージ スペースの量の尺度です。
空間複雑度はプログラムが占めるバイト数ではありません。これはあまり意味がないため、空間複雑度は変数の数によって計算されます。
空間計算量の計算ルールは基本的に実際の計算量と同様であり、ビッグ O の漸近表記も使用されます。
注: 実行時に関数に必要なスタック スペース (ストレージ パラメーター、ローカル変数、一部のレジスタ情報など) はコンパイル中に決定されるため、スペースの複雑さは主に、実行時に関数によって明示的に要求される追加スペースによって決まります
。
例 1:
// 计算BubbleSort的空间复杂度?
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;
}
}
前回の記事で時間計算量が O(N^2) であると述べた上記のバブル ソートでは、時間計算量は実際には O(1) であり、前に説明したビッグ O 漸近法と似ています。作成したプログラム 変数はすべて定数項なので、O(1)です。
空間の複雑さでは、空間は蓄積されるのではなく、時間は蓄積されるという規則を覚えておく必要があります。
// 计算Fibonacci的空间复杂度?
// 返回斐波那契数列的前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;
}
これはフィボナッチの反復であるため、時間計算量は O(N) ですが、malloc によって空間が開かれたため、空間計算量も O(N) になります。
long long Fac(size_t N)
{
if (N == 0)
return 1;
return Fac(N - 1) * N;
}
誰もがこの空間の複雑さは O(2^n) であると考えるかもしれませんが、実際には O(N) です。関数スタック フレームの作成が破棄され、多くの空間が再利用されるためです。は累積されませんが、時間は累積されます。
4. 一般的な複雑さの比較
一般的なアルゴリズムの一般的な複雑さは次のとおりです。
一般に、後者のいくつかのアルゴリズムは使用されず、遅すぎます。
ここでは誰もができるいくつかの OJ の質問を紹介します
アイデア 1
ハッシュの考え方を使用できます。つまり、最初に配列を用意し、その内容が -1 に初期化され、次にその数値を対応する配列に入れて、配列が - の場合はその配列を走査します。 1、次に、検索する値。
int missingNumber(int* nums, int numsSize){
int*num=(int*)malloc(sizeof(int)*(numsSize+1));
int i=0;
for(i=0;i<=numsSize;i++)
{
num[i]=-1;
}
for(i=0;i<numsSize;i++)
{
num[nums[i]]=nums[i];
}
for(i=0;i<=numsSize;i++)
{
if(num[i]==-1)
return i;
}
free(num);
return NULL;
}
最初に
書いたときはコンパイルエラーを修正し続けましたが、実際には戻り値が抜けていますが、これを main 関数と同じように VS に置いてデバッグすることができます。
#include<stdio.h>
#include<stdlib.h>
int missingNumber(int* nums, int numsSize) {
int* num = (int*)malloc(sizeof(int) * (numsSize + 1));
int i = 0;
for (i = 0; i <= numsSize; i++)
{
num[i] = -1;
}
for (i = 0; i < numsSize; i++)
{
num[nums[i]] = nums[i];
}
for (i = 0; i <= numsSize; i++)
{
if (num[i] == -1)
return i;
}
free(num);
return NULL;
}
int main()
{
int arr[] = {
2,3,4,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
int ret=missingNumber(arr, sz);
printf("%d", ret);
return 0;
}
アイデア 2
ビット単位の XOR は、非常に高速なアイデアです。0 と任意の数値の XOR はそれ自体であるため、0 を与えるだけで済みます。その後、同じ数値の XOR は 0 であるため、コードを見てください。
int missingNumber(int* nums, int numsSize){
int x=0;
for(int i=0;i<numsSize;i++)
{
x^=nums[i];
}
for(int i=0;i<=numsSize;i++)
{
x^=i;
}
return x;
}
実はまだアイデアはあるのですが、書きません。アイデア
3、最初にソートし、次に検索し、順番に 1 つずつトラバースしますが、ソートには時間がかかるため、空間の複雑さは明らかに O(N) ではありません。
アイデア 4、0 から N までの数値を加算し、この配列を減算すると、消える数値が得られます。
void revolve(int*left,int*right)
{
while(left<right)
{
int tmp=*left;
*left=*right;
*right=tmp;
left++;
right--;
}
}
void rotate(int* nums, int numsSize, int k){
if(numsSize==1)
return ;
k=k%numsSize;
revolve(nums,nums+numsSize-1);
revolve(nums,nums+k-1);
revolve(nums+k,nums+numsSize-1);
}
今日の共有はここまでです。また次回お会いしましょう