You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在C语言中去除多余重复字符?关键词密码去重问题求助

解决关键词密码中的重复字符问题及C语言通用去重方法

嘿,我来帮你搞定这个关键词密码里的重复字符问题!你遇到的末尾出现多个z的情况,大概率是构建新字母表时的逻辑出错了——要么是没正确标记关键词里的字符,导致重复添加未被移除的字符,要么是循环边界处理不当。咱们一步一步来解决:

一、针对关键词密码的具体解决方案

关键词密码的核心逻辑是:先把去重后的关键词放在新字母表开头,再按顺序添加剩下未出现在关键词里的字母。这里的关键是标记已使用的字符,避免重复添加。

示例代码

#include <stdio.h>
#include <string.h>
#include <ctype.h>

// 构建去除关键词字符后的新字母表
void buildKeywordAlphabet(const char *keyword, char *result) {
    int used[26] = {0}; // 标记a-z是否已被使用,初始全为0(未使用)
    int idx = 0;

    // 第一步:处理关键词,去重后添加到结果,并标记已使用字符
    for (int i = 0; keyword[i] != '\0'; i++) {
        char c = tolower(keyword[i]); // 统一转为小写,兼容大小写输入
        if (c >= 'a' && c <= 'z' && !used[c - 'a']) {
            used[c - 'a'] = 1;
            result[idx++] = c;
        }
    }

    // 第二步:添加剩余未被使用的字母
    for (char c = 'a'; c <= 'z'; c++) {
        if (!used[c - 'a']) {
            result[idx++] = c;
        }
    }
    result[idx] = '\0'; // 字符串结束符,必须加上
}

int main() {
    char keyword[] = "helo";
    char alphabet2[27]; // 26个字母+结束符,足够存储结果
    buildKeywordAlphabet(keyword, alphabet2);
    printf("处理后的字母表:%s\n", alphabet2);
    // 输出应为:heloabcdfgijkmnpqrstuvwxyz
    return 0;
}

代码解释

  1. 标记数组used:用大小为26的数组对应a-z每个字符,标记是否已经被添加到新字母表中。
  2. 关键词去重:遍历关键词时,只添加第一次出现的字符,避免关键词本身有重复字符(比如hello里的两个l)导致的错误。
  3. 顺序添加剩余字母:从a到z遍历,只添加未被标记的字符,确保每个字母只出现一次。

二、C语言中去除字符串重复字符的通用方法

根据不同的场景(是否允许修改顺序、是否有额外空间限制),有几种常用的方法:

1. 标记数组法(高效,适合ASCII字符)

原理:用数组记录每个字符是否已出现,遍历字符串时只保留第一次出现的字符。
优点:时间复杂度O(n),效率极高;缺点:需要额外的数组空间,不支持Unicode字符。

#include <string.h>

void removeDuplicates(char *str) {
    int seen[256] = {0}; // 覆盖所有ASCII字符
    int idx = 0;
    for (int i = 0; str[i] != '\0'; i++) {
        unsigned char c = str[i];
        if (!seen[c]) {
            seen[c] = 1;
            str[idx++] = c;
        }
    }
    str[idx] = '\0';
}

2. 双重循环法(无额外空间,适合短字符串)

原理:外层循环遍历每个字符,内层循环检查该字符是否已经在前面出现过,重复则跳过。
优点:不需要额外空间;缺点:时间复杂度O(n²),长字符串效率低。

#include <string.h>

void removeDuplicatesNoExtraSpace(char *str) {
    int len = strlen(str);
    if (len <= 1) return;

    int idx = 1;
    for (int i = 1; i < len; i++) {
        int j;
        // 检查当前字符是否已在前面的结果中
        for (j = 0; j < idx; j++) {
            if (str[i] == str[j]) break;
        }
        if (j == idx) {
            str[idx++] = str[i];
        }
    }
    str[idx] = '\0';
}

3. 排序去重法(适合长字符串,允许改变顺序)

原理:先对字符串排序,让重复字符相邻,再遍历跳过重复项。
优点:长字符串效率较高(时间复杂度O(n log n));缺点:会改变原字符串的字符顺序。

#include <string.h>
#include <stdlib.h>

// qsort的比较函数
int compareChars(const void *a, const void *b) {
    return *(const unsigned char *)a - *(const unsigned char *)b;
}

void removeDuplicatesSorted(char *str) {
    qsort(str, strlen(str), sizeof(char), compareChars);
    int idx = 0;
    for (int i = 0; str[i] != '\0'; i++) {
        // 只保留第一个出现的字符
        if (i == 0 || str[i] != str[i-1]) {
            str[idx++] = str[i];
        }
    }
    str[idx] = '\0';
}

内容的提问来源于stack exchange,提问作者Macaraune Salad

火山引擎 最新活动