データ構造 - 空間の複雑さ

ここに画像の説明を挿入
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 に初期化され、次にその数値を対応する配列に入れて、配列が - の場合はその配列を走査します。 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);
}

ここに画像の説明を挿入
今日の共有はここまでです。また次回お会いしましょう

おすすめ

転載: blog.csdn.net/2301_76895050/article/details/132218316
おすすめ