如何在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; }
代码解释
- 标记数组
used:用大小为26的数组对应a-z每个字符,标记是否已经被添加到新字母表中。 - 关键词去重:遍历关键词时,只添加第一次出现的字符,避免关键词本身有重复字符(比如
hello里的两个l)导致的错误。 - 顺序添加剩余字母:从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




