[英]Possible combinations of characters on a phone's numpad
我最近在C語言中遇到了一個問題。我們的手機小鍵盤布局如下:
1[abc] 2[def] 3[ghi] 4[jkl] 5[mno] 6[pqr] 7[st] 8[uv] 9[wx] 0[yz]
如何提出一個API,該API可以為給定的數字輸入提供屬於每個數字的所有可能字符組合。 例如input = 1234
然后,API應打印所有可能的字符組合-
adgj
bdgj
cdgj
aegj
begj
cegj
..等。
有簡單的方法嗎? 除了硬編碼嵌套for
循環。 給了我一個暗示,那就是遞歸,但是我想不出辦法。
對於必須在其中找到組合的此類問題,遞歸是一個很好的解決方案。 與嵌套循環相比,優點是遞歸適用於任何長度的字符串。
在您的情況下,您需要一個具有以下功能的函數:
char
緩沖區*和 遞歸函數需要終止條件:到達原始字符串的末尾時,將其打印並返回。
否則,取下一個數字,檢查它是否有效,確定與之關聯的字母,然后為每個字母調用函數。 也就是說,對於每個字母,將其復制到當前索引處的解決方案中,然后使用下一個索引來調用該函數。
以下是使用中間函數執行一些內部管理的示例實現:
#include <stdlib.h>
#include <stdio.h>
/*
* Recursive back-end, that produces all combinations in sol.
*/
void alpha_r(const char *str, char *sol, int index)
{
const char *combo[] = {
"yz", "abc", "def", "ghi", "jkl", "mno", "pqr", "st", "uv", "wx"
};
if (str[index] == '\0') {
printf("%s\n", sol);
} else {
int k = str[index] - '0';
const char *p = combo[k];
while (*p) {
sol[index] = *p++;
alpha_r(str, sol, index + 1);
}
}
}
/*
* Non-recursive front-end that checks the string for validity
* and creates a temporary buffer for the solutions.
*/
void alpha(const char *str)
{
int len = 0;
while (str[len]) {
if (str[len] < 0 || str[len] > '9') {
fprintf(stderr, "Invalid input.\n");
return;
}
len++;
}
char sol[len + 1];
sol[len] = '\0';
alpha_r(str, sol, 0);
}
int main()
{
alpha("123");
return 0;
}
*)您也可以使用字符串本身來存儲解決方案。
遞歸只是嵌套四個for
循環的一種偷偷摸摸的方法。 這是代碼的樣子
#include <stdio.h>
void sneaky( int depth, int maxDepth, char str[] )
{
char c, start;
start = 'a' + depth * 3;
for ( c = start; c < start + 3; c++ )
{
str[depth] = c;
str[depth+1] = '\0';
if ( depth == maxDepth )
printf( "%s\n", str );
else
sneaky( depth + 1, maxDepth, str );
}
}
int main( void )
{
char str[5] = { 0 };
sneaky( 0, 3, str );
}
您還可以使用簡單的計數算法解決此問題以及類似的組合問題。 計數算法模擬自然計數,其中您將最低有效位從0遞增到9。當最低有效位從9回繞到0時,左邊的下一位遞增。
可以解決OP的問題。 但是在這種情況下,數字具有兩個或三個可能的值。 而且,如果您檢查OP中的模式,則很顯然最低有效數字在左側。 在模式
adgj
bdgj
cdgj
aegj
您會看到a
變成b
, b
變成c
,當c
返回到a
, d
變成e
。
這是代碼
#include <stdio.h>
#include <stdlib.h>
static char InitialValue[] = { 'y', 'a', 'd', 'g', 'j', 'm', 'p', 's', 'u', 'w' };
static char NextValue[] = { 'b', 'c', 'a', 'e', 'f', 'd', 'h', 'i', 'g',
'k', 'l', 'j', 'n', 'o', 'm', 'q', 'r', 'p',
't', 's', 'v', 'u', 'x', 'w', 'z', 'y' };
static void error( char *msg )
{
fprintf( stderr, "%s\n", msg );
exit( EXIT_FAILURE );
}
int main( void )
{
int i, oldDigit;
char str[12];
// get the input string from the user
printf( "Enter the input string: " );
fflush( stdout );
if ( scanf( "%10s", str ) != 1 )
error( "whatever" );
// convert the input string to the corresponding first output string
for ( i = 0; str[i] != '\0'; i++ )
{
if ( str[i] < '0' || str[i] > '9' )
error( "invalid input string" );
str[i] = InitialValue[str[i] - '0'];
}
printf( "%s\n", str );
// use a simple counting algorithm to generate the string combinations
for (;;)
{
for ( i = 0; str[i] != '\0'; i++ )
{
oldDigit = str[i]; // save the current digit
str[i] = NextValue[oldDigit - 'a']; // advance the digit to the next value
if ( str[i] > oldDigit ) // if the digit did not wrap
break; // then we've got a new string
}
if ( str[i] == '\0' ) // if all the digits wrapped
break; // then we're done
printf( "%s\n", str ); // output the new string
}
return( EXIT_SUCCESS );
}
(順便說一下,這不是電話的標准布局。)
棘手的部分是處理數據結構。 輸入字符串由數字組成很方便,因為這樣我們就可以使用字符串中的數字來索引一個數組,該數組包含每個數字的可能字母。
想法是使用for循環修改特定索引處的輸出字符串,以遍歷該索引處的所有可能替換。 然后遞歸移動到for循環主體中輸出數組中的下一個索引。
如果到達數組末尾,則打印並返回。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* data[] = {"0", "1", "2abc", "3def", "4ghi", "5jkl", "6mno", "7prs", "8tuv", "9wxy"};
char* input = "23456783";
char* arr;
void current(int index)
{
if(index == strlen(input)) printf("%s\n", arr);
else
{
for(int i = 0; i < strlen(data[input[index] - '0']); ++i)
{
arr[index] = data[input[index] - '0'][i];
current(index + 1);
}
}
}
void main()
{
arr = malloc(strlen(input) + 1);
arr[strlen(input)] = '\0';
printf("%s\n\n", input);
current(0);
}
查找所要查找的組合的一種方法可能是按位邏輯,即二進制數和整數。 二進制數將與字符串一樣長,其中0和1充當字符串中包含和排除的內容的打開和關閉開關。 這里的事情是,我們根據數字“按下”使用基數3或4,並且
如果以4為底數,則必須應用一些if語句將那些實際上是以3為底數的語句移動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.