該問題可以分爲兩個任務:(1)查找數字數組的所有子序列和(2)打包並將整數解壓縮爲數字。
我們來考慮數組{a, b, c}
的子序列。您可以通過從左到右的方式遍歷數組來生成它們,並遵循兩條路徑:一個包含子序列中的當前元素,另一個包含您不包含的元素。
這導致一個遞歸方法達,我們可以表示成一棵樹:
{}
/ \
{} {a}
/ \ / \
{} {b} {a} {ab}
/\ / \ / \ / \
{} {c} {b} {bc} {a} {ac} {ab} {abc}
當我們離開分支化,我們跳過當前元素,當我們走正確的,我們包括的元素。元素本身就是樹的深度:在第一級,我們將元素a
,下一個b
和最後一個c
。
底行有所有子序列。這包括您不想要的空序列和完整序列。但現在讓我們包括它們。 (底行中的數組通常被稱爲power set,這是一個很好的網頁搜索術語。)
我提到了遞歸,這需要遞歸函數和函數。
所以我們需要以另一種方式解決問題。讓我們轉一下樹。短劃線表示該元素被跳過。右邊的符號使用另一個符號:0
意味着元素被跳過,1
意味着元素被列入:
- - - 000
- - c 001
- b - 010
- b c 011
a - - 100
a - c 101
a b - 110
a b c 111
我希望在右邊的代碼看起來很熟悉,因爲這是你如何指望從000
在111
二進制文件。這是列舉我們元素的一個好方法。現在我們需要一種方法來確定每個數字中設置了哪些位。
當數字爲奇數時,設置最右邊的位。我們可以通過重複將數字除以2來找出其他位,這在二進制中是向右移位,丟棄最右邊的位。
現在如何從原始數字中提取數字?該數字是十進制數字;它的基數爲10.我們可以使用與查找二進制數中的位相同的方法,因爲位0和位1是二進制數字。
以數字開頭。最後一位數字是將除法後的餘數除以10得到的結果。然後將數字除以10直到它爲零。這段代碼從右到左產生數字。查找位的代碼也是這樣,這意味着我們可以找到是否設置了一位,並在單個循環中打印哪個數字,始終佔據最右邊的位,如果已設置,則打印原始數字的最右邊的數字。
空的和完整的子序列是枚舉中的第一個和最後一個項目。如果你不想要它們,跳過它們。
如果數字有重複數字,則會留下重複子序列的問題。我看不出一個簡單的方法來解決這個問題,除了user3629249建議創建子序列並稍後檢查是否已經打印。
一個簡單的方法來做到這一點是保持一個子序列的數組。該數組有max
條目。填充該數組後,對其進行排序並打印,但跳過與前一條目相同的條目。
下面是一個使用數字數組的示例實現,以便每次都不必分解原始數字。它使用排序功能qsort
從<stdlib.h>
,這需要一個排序功能:
#include <stdlib.h>
#include <stdio.h>
#define NUM 412131
typedef unsigned int uint;
int uintcmp(const void *pa, const void *pb)
{
const uint *a = pa;
const uint *b = pb;
return (*a > *b) - (*a < *b);
}
int main(void)
{
uint digit[20]; // array of digits
size_t ndigit = 0; // length of array
uint num = NUM;
uint max = 1;
size_t i;
while (num) {
digit[ndigit++] = num % 10;
num /= 10;
max *= 2;
}
uint res[max]; // array of subsequences
for (i = 0; i < max; i++) {
uint mask = i; // mask for bit detection
uint j = ndigit; // index into digit array
uint s = 0;
while (j--) {
if (mask % 2) s = s*10 + digit[j];
mask /= 2;
}
res[i] = s;
}
qsort(res, max, sizeof(*res), uintcmp);
for (i = 1; i < max - 1; i++) {
if (res[i] != res[i - 1]) printf("%u\n", res[i]);
}
return 0;
}
_and不使用functions_ - 這有什麼不好的功能呢?正確使用,他們可以使代碼更易於理解。 –
'max = max-2'添加分號可以消除編譯器錯誤,如果這就是您認爲的「高效」。 – Downvoter
哇,對不起,我做了一個改變,忘了。 – riegour