Memory Limit Exceeded(內存超限)
出現超內存時我們需要對自己的程序的空間複雜度進行優化,此處的空間複雜度是與時間複雜度相對應的。
空間複雜度:
空間複雜度(Space Complexity)是對一個算法在運行過程中臨時佔用存儲空間大小的量度,記做S(n)=O(f(n))。比如直接插入排序的時間複雜度是O(n^2),空間複雜度是O(1) 。而一般的遞歸算法就要有O(n)的空間複雜度了,因爲每次遞歸都要存儲返回信息。一個算法的優劣主要從算法的執行時間和所需要佔用的存儲空間兩個方面衡量。
類似於 [1] 時間複雜度的討論,它也是問題規模n的函數。
一個算法在計算機存儲器上所佔用的存儲空間,包括存儲算法本身所佔用的存儲空間,算法的輸入輸出數據所佔用的存儲空間和算法在運行過程中臨時佔用的存儲空間這三個方面。
存儲算法本身所佔用的存儲空間:與算法書寫的長短成正比,要壓縮這方面的存儲空間,就必須編寫出較短的算法。
算法的輸入輸出數據所佔用的存儲空間:是由要解決的問題(問題規模)決定的,是通過參數表由調用函數傳遞而來的,它不隨本算法的不同而改變。
算法在運行過程中臨時佔用的存儲空間:隨算法的不同而異。 (來自百度百科)
分析空間複雜度:
算法的空間複雜度一般也以數量級的形式給出。如當一個算法的空間複雜度爲一個常量,即不隨被處理數據量n的大小而改變時,可表示爲O(1);當一個算法的空間複雜度與以2爲底的n的對數成正比時,可表示爲O(log2n);當一個算法的空間複雜度與n成線性比例關係時,可表示爲O(n).若形參爲數組,則只需要爲它分配一個存儲由實參傳送來的一個地址指針的空間,即一個機器字長空間;若形參爲引用方式,則也只需要爲其分配存儲一個地址的空間,用它來存儲對應實參變量的地址,以便由系統自動引用實參變量。 (來自百度百科)
避免的方法:
只能是跟據題目所給出的數據範圍,看一看數組開闢的能不能再小一些,或者更改算法以使用更小的內存。
其它莫名導致MLE的題:
1. 做字典樹,AC自動機
把存樹結點的數組,在init()初始化函數中一次性清零。MLE。。。
void init() //初始化
{
while(!qu.empty())
qu.pop();
mem(ne, 0);//
mem(fail,0);
mem(vis,0);
mem(book,0);
tot=1;
}
void Insert(char *str,int y) //插入字符串
{
int ls=strlen(str);
int rt=0;
for(int i=0; i<ls; i++)
{
int x=str[i]; //把字符串的字符存入字典樹
if(!ne[rt][x])
ne[rt][x]=tot++; //若這一字符沒有在這一分支 ,節點數+1;
rt=ne[rt][x];
}
vis[rt]=y+1;
// printf("stateT_cnt==%d\n",stateT[rt].cnt);
}
要在建樹的時候一個一個清零。。。 就是要保證只清零了要用的點; AC
void init() //初始化
{
while(!qu.empty())
qu.pop();
mem(ne[0], 0);//
fail[0]=-1;
tot=1;
}
void Insert(char *str,int y) //插入字符串
{
int ls=strlen(str);
int rt=0;
for(int i=0; i<ls; i++)
{
int x=str[i]; //把字符串的字符存入字典樹
if(!ne[rt][x])
{
mem(ne[tot],0);
fail[tot]=-1;
ne[rt][x]=tot++; //若這一字符沒有在這一分支 ,節點數+1;
}
rt=ne[rt][x];
}
vis[rt]=y;
// printf("stateT_cnt==%d\n",stateT[rt].cnt);
}
2. 數學題 (Smith Numbers)
vector<int>ve; 在get_s裏可以調用gt_n; 我沒用get_n,重新又寫一遍,結果MLE
ll get_n(ll x)
{
ll ans=0;
while(x)
{
ans += x%10;
x/=10;
}
return ans;
}
ll get_s(ll x)
{
ll ans=0;
prime_decompose(x);
for(ll i=0;i<ve.size();i++)
{
// printf("ve%d ",ve[i]);
while(ve[i])
{
ans += ve[i]%10;
ve[i] /= 10;
}
}
return ans;
}
調用了的,AC
ll get_n(ll x)
{
ll ans=0;
while(x)
{
ans += x%10;
x/=10;
}
return ans;
}
ll get_s(ll x)
{
ll ans=0;
prime_decompose(x);
for(ll i=0;i<ve.size();i++)
{
// printf("ve%d ",ve[i]);
// while(ve[i])
// {
// ans += ve[i]%10;
// ve[i] /= 10;
// }
ans+=get_n((ll)ve[i]);
}
return ans;
}