C语言编程--14.电话号码的字母组合

题目:

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1

输入:digits = "23"

输出:"ad","ae","af","bd","be","bf","cd","ce","cf"

示例 2

输入:digits = ""

输出:\[\]

示例 3

输入:digits = "2"

输出:"a","b","c"

提示

0 <= digits.length <= 4

digitsi 是范围 '2', '9' 的一个数字。

代码:

(1)蛮力法:

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
char** letterCombinations(char* digits, int* returnSize) {
    char data[8][5] = {
        "abc",
        "def",
        "ghi",
        "jkl",
        "mno",
        "pqrs",
        "tuv",
        "wxyz"
    };
    *returnSize = 0;

    int len = strlen(digits);
    if (len == 0) {
        return NULL;
    }

    // 计算最大可能的组合数
    int maxCombinations = 1;
    for (int i = 0; i < len; i++) {
        if (digits[i] == '7' || digits[i] == '9') {
            maxCombinations *= 4;
        } else {
            maxCombinations *= 3;
        }
    }

    // 动态分配结果数组的内存
    char **result = (char **)malloc(maxCombinations * sizeof(char *));
    for (int i = 0; i < maxCombinations; i++) {
        result[i] = (char *)malloc((len + 1) * sizeof(char));
        result[i][0] = '\0';
    }

    if (len == 1) {
        char *letters = data[digits[0] - '2'];
        for (int i = 0; letters[i] != '\0'; i++) {
            result[*returnSize][0] = letters[i];
            result[*returnSize][1] = '\0';
            (*returnSize)++;
        }
    } else if (len == 2) {
        char *letters1 = data[digits[0] - '2'];
        char *letters2 = data[digits[1] - '2'];
        for (int i = 0; letters1[i] != '\0'; i++) {
            for (int j = 0; letters2[j] != '\0'; j++) {
                result[*returnSize][0] = letters1[i];
                result[*returnSize][1] = letters2[j];
                result[*returnSize][2] = '\0';
                (*returnSize)++;
            }
        }
    } else if (len == 3) {
        char *letters1 = data[digits[0] - '2'];
        char *letters2 = data[digits[1] - '2'];
        char *letters3 = data[digits[2] - '2'];
        for (int i = 0; letters1[i] != '\0'; i++) {
            for (int j = 0; letters2[j] != '\0'; j++) {
                for (int k = 0; letters3[k] != '\0'; k++) {
                    result[*returnSize][0] = letters1[i];
                    result[*returnSize][1] = letters2[j];
                    result[*returnSize][2] = letters3[k];
                    result[*returnSize][3] = '\0';
                    (*returnSize)++;
                }
            }
        }
    } else if (len == 4) {
        char *letters1 = data[digits[0] - '2'];
        char *letters2 = data[digits[1] - '2'];
        char *letters3 = data[digits[2] - '2'];
        char *letters4 = data[digits[3] - '2'];
        for (int i = 0; letters1[i] != '\0'; i++) {
            for (int j = 0; letters2[j] != '\0'; j++) {
                for (int k = 0; letters3[k] != '\0'; k++) {
                    for (int m = 0; letters4[m] != '\0'; m++) {
                        result[*returnSize][0] = letters1[i];
                        result[*returnSize][1] = letters2[j];
                        result[*returnSize][2] = letters3[k];
                        result[*returnSize][3] = letters4[m];
                        result[*returnSize][4] = '\0';
                        (*returnSize)++;
                    }
                }
            }
        }
    }

    return result;
}

蛮力法做的话,需要有很清晰的逻辑思路,对嵌套循环有较深的了解和掌握。

(2)回溯法

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void backtrack(char* digits, int index, char** data, char* current, char** result, int* returnSize) {
    if (digits[index] == '\0') {
        result[*returnSize] = strdup(current);
        (*returnSize)++;
        return;
    }

    int digit = digits[index] - '2';
    char* letters = data[digit];
    for (int i = 0; letters[i] != '\0'; i++) {
        current[index] = letters[i];
        backtrack(digits, index + 1, data, current, result, returnSize);
    }
}

char** letterCombinations(char* digits, int* returnSize) {
    char* data[8] = {
        "abc",
        "def",
        "ghi",
        "jkl",
        "mno",
        "pqrs",
        "tuv",
        "wxyz"
    };
    *returnSize = 0;

    int len = strlen(digits);
    if (len == 0) {
        return NULL;
    }

    int maxCombinations = 1;
    for (int i = 0; i < len; i++) {
        if (digits[i] == '7' || digits[i] == '9') {
            maxCombinations *= 4;
        } else {
            maxCombinations *= 3;
        }
    }

    char** result = (char**)malloc(maxCombinations * sizeof(char*));
    char* current = (char*)malloc((len + 1) * sizeof(char));
    current[len] = '\0';

    backtrack(digits, 0, data, current, result, returnSize);

    free(current);
    return result;
}

采用回溯算法来生成所有可能的字母组合,这样可以避免嵌套循环过多的问题。

  1. 回溯函数 backtrack:
    当处理完所有数字时,将当前组合复制到结果数组。
    对于每个数字,遍历其对应的字母,递归处理下一个数字。
  2. 主函数 letterCombinations:
    若输入为空,返回 NULL。
    计算可能的组合数量,为结果数组分配内存。
    分配一个临时数组 current 用于存储当前组合。
    调用 backtrack 函数生成组合。
    释放临时数组的内存。
相关推荐
Highcharts.js2 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
头发还在的女程序员3 小时前
医院陪诊管理系统怎么选择?——2026 年选型避坑与架构参考
java·开发语言·陪诊系统·陪诊app·医院陪诊陪护
拳里剑气5 小时前
C++算法:BFS解决FloodFill算法
c++·算法·bfs·宽度优先
爱写代码的小朋友5 小时前
从零开始学 Win32 API:C++ 窗口编程实战(VS Code + MinGW-w64 命令行详解)
开发语言·c++
果汁华5 小时前
Function Calling 与 Python 实战完整指南
开发语言·网络·python
小小晓.6 小时前
C++:语句和作用域
开发语言·c++
wanderist.7 小时前
Lambda表达式在算法竞赛中的应用
java·开发语言·算法
稚南城才子,乌衣巷风流7 小时前
支配树(Dominator Tree)详解:概念、算法与应用
算法
海天鹰7 小时前
PHP上传文件
android·开发语言·php