整数因子分解c语言递归,整数因子分解:计算一个整数所有的分解式(递归实现)...
原始問題描述:
對于給定的正整數n,計算n有多少種不同的分解式。
例如,當n=12時,有8種不同的分解式:
12=12,
12=6×2,
12=4×3,
12=3×4,
12=3×2×2,
12=2×6,
12=2×3×2 ,
12=2×2×3
對n的每個因子遞歸搜索,代碼如下:
void solve (int n)
{
if (n==1)
total++;
else
for (int i=2; i<=n; i++)
if (n%i==0)
solve (n/i);
}
擴展問題一:能否輸出各種具體的分解表達式?
思路:可以設置一個棧,如果是因子,則將這個因子壓入棧中,遞歸到因子為1時分解完畢,將整個棧中元素輸出。一次遞歸結束后將棧頂的元素彈出(本例中用的vector容器模擬棧)。代碼如下:
void solve(int n)
{
if (n == 1)
{
total++;
print_vector(ivec);//輸出棧中的元素
}
else
for (int i = 2; i <= n; i++)
if (n % i == 0)
{
//如果i是n的因子,則將i壓入棧
ivec.push_back(i);
solve(n / i);
ivec.pop_back();//出棧
}
}
擴展問題二:能否輸出不重復的分解表達式?
第一種思路:經過多次試驗發現,如果遞歸結束時,模擬棧中的元素是無序的,則本次分解一定重復。以12為例,有3種情況為:2×2×3、2×3×2、3×2×2,后兩種之所以重復,是因為它們都是無序的,因此,在上問題一的基礎上,只須在輸出之前判斷一下模擬棧中的元素是否有序便可,若序時,才進行輸出。代碼如下:
void solve(int n)
{
if (n == 1)
{
total++;
if (isOrderVector(ivec))//只有有序時,才輸出
print_vector(ivec);//輸出棧中的元素
}
else
for (int i = 2; i <= n; i++)
if (n % i == 0)
{
//如果i是n的因子,則將i壓入棧
ivec.push_back(i);
solve(n / i);
ivec.pop_back();//出棧
}
}
其中判斷模擬棧是否為有序的代碼如下:
bool isOrderVector(vector & ivec)
{
assert(ivec.size() > 0);
for (vector::iterator i = ivec.begin() + 1; i != ivec.end(); i++)
if (*i < *(i-1))
return false;
return true;
}
問題二的進一步優化:其實slove()函數內層循環中i沒有必要循環到n,只須要循環到sqrt(n)便可,當然,需要再補上缺失的一種情況:當i為n時,代碼如下:
void solve(int n)
{
……
else
{
for (int i = 2; i <= sqrt(n); i++)
{
if (n % i == 0)
{
//如果i是n的因子,則將i壓入棧
ivec.push_back(i);
solve(n / i);
ivec.pop_back();//出棧
}
}
{
ivec.push_back(n);
slove(1);
ivec.pop_back();
}
}
}
第二種思路[章磊同學提供]:
既然為了保持模擬棧中元素的順序,那每次i入棧之前先同棧頂元素進行比較,如果i大于棧頂元素,則不入棧,這種方法更簡潔,代碼如下:
void solve(int n)
{
if (n == 1)
{
total++;
print_vector(ivec);//輸出棧中的元素
}
else
for (int i = 2; i <= n; i++)
if (n % i == 0)
{
//若棧不為空,且i比棧頂元素小,說明
//再壓棧己沒有意義,直接結束本次循環。
if ((ivec.size() > 0) && i < ivec[ivec.size()-1])
continue;
//如果i是n的因子,則將i壓入棧
ivec.push_back(i);
solve(n / i);
ivec.pop_back();//出棧
}
}
參考資料:北京科技大學 羅熊 算法設計與分析 第三章課件
總結
以上是生活随笔為你收集整理的整数因子分解c语言递归,整数因子分解:计算一个整数所有的分解式(递归实现)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 快速排序 数组 函数 c语言,书上快速排
- 下一篇: 电脑基础c语言,C语言经验: 如何从零基