每日一题(4.18)

Leecode-187-重复的DNA序列

题目

DNA序列 由一系列核苷酸组成,缩写为 ‘A’, ‘C’, ‘G’ 和 ‘T’.。

例如,“ACGAATTCCG” 是一个 DNA序列 。
在研究 DNA 时,识别 DNA 中的重复序列非常有用。

给定一个表示 DNA序列 的字符串 s ,返回所有在 DNA 分子中出现不止一次的 长度为 10 的序列(子字符串)。你可以按 任意顺序 返回答案。

示例

示例1

输入:s = “AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT”
输出:[“AAAAACCCCC”,“CCCCCAAAAA”]

示例2

输入:s = “AAAAAAAAAAAAA”
输出:[“AAAAAAAAAA”]

解题思路

  • 辅助函数:
    1. DNAHash* FindDna(char *s, int begin):从哈希表中查找从s的begin位置开始的长度为10的子串。如果找到,返回对应的DNAHash结构体指针;否则返回NULL。
    2. int GetDnaCnt(char *s, int begin):返回从s的begin位置开始的长度为10的子串在哈希表中出现的次数。
    3. void AddDna2Hash(char *s, int begin):将从s的begin位置开始的长度为10的子串添加到哈希表中。如果该子串已经存在,则增加其计数;否则,创建一个新的DNAHash结构体并添加到哈希表中。
    4. 主函数:
      char ** findRepeatedDnaSequences(char * s, int* returnSize):这是主要的函数,用于查找并返回所有出现至少两次的、长度为10的连续子串。
      · 首先,它计算了DNA字符串s的长度。
      · 初始化一个结果数组result,用于存储找到的重复子串。
      · 遍历字符串s,从每个可能的起始位置开始,长度为10的子串被添加到哈希表中。
      · 如果某个子串的计数达到2(即它第二次出现),则将其添加到结果数组中。
      · 在完成所有操作后,遍历哈希表并释放其占用的内存。
      · 最后,返回结果数组并设置returnSize为结果数组中的子串数量。

代码实现

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
#define LEN 10

typedef struct DnaHash{
    char dna[LEN + 1];
    int cnt;
    UT_hash_handle hh;
}DnaHash;

DnaHash* Dnahead = NULL;

DnaHash* FindDna(char* s,int begin){
    DnaHash* flag = NULL;
    char tmp[LEN+1] = {0};
    strncpy(tmp, s + begin, LEN);  
    HASH_FIND_STR(Dnahead, tmp, flag);
    return flag;
}

int GetDnaCnt(char *s, int begin){
    DnaHash* tmp = FindDna(s, begin);
    if(tmp != NULL){
        return tmp->cnt;
    }else{
        return 0;
    }
}

void AddDnaToHash(char *s,int begin){
    DnaHash *tmp = FindDna(s, begin);
    if(tmp == NULL){
        tmp = (DnaHash *)malloc(sizeof(DnaHash));
        memset(tmp, 0, sizeof(DnaHash));
        strncpy(tmp->dna, s + begin, LEN);
        tmp->cnt = 1;
        HASH_ADD_STR(Dnahead, dna, tmp);
    }else{
        (tmp->cnt)++;
    }
}

char ** findRepeatedDnaSequences(char * s, int* returnSize){
    int len = strlen(s);
    char **res = (char **)malloc(sizeof(char*)*len);
    int cnt = 0;
    for(int i = 0; i <= len - LEN; i++){
        AddDnaToHash(s, i);
        if(GetDnaCnt(s, i) == 2){
            char* tmp = (char*)malloc(LEN + 1); 
            memset(tmp, 0, LEN + 1);
            strncpy(tmp, s + i, LEN);
            res[cnt++] = tmp;
        }
    }
    DnaHash* pPrev = NULL;
    DnaHash* pCurrent = NULL;
    HASH_ITER(hh, Dnahead, pPrev, pCurrent) {
        HASH_DEL(Dnahead, pPrev);
        free(pPrev);
    }
    Dnahead = NULL;

    *returnSize = cnt;
    return res;
}

Leecode-1047-删除字符串中的所有相邻重复项

题目

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例

输入:“abbaca”
输出:“ca”
解释:
例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。

解题思路

  1. 初始化res为输入字符串s的第一个字符,并设置索引index为1,准备写入下一个字符。

  2. 遍历s中的每一个字符,从第二个字符开始(因为第一个字符已经放在res中了)。

  3. 对于s中的每一个字符,检查它是否与前一个放入res的字符相同。如果不同,或者res为空(即index为0),则将其放入res中,并增加index。

  4. 如果s中的当前字符与res的最后一个字符相同,则将index减1,这样res中的最后一个字符就被覆盖了,相当于去除了重复字符。

  5. 最后,在res的index位置加上字符串结尾的’\0’。

  6. 返回res,这是去除连续重复字符后的结果字符串。

代码实现

char* removeDuplicates(char* s) {
    int len = strlen(s);
    int index = 1;
    char *res = malloc(sizeof(char)*(len+1));
    res[0] = s[0];
    for(int i = 1; i < len; i++){
        if(index == 0 || s[i] != res[index - 1]){
           res[index] = s[i];
            index++;
        }
        else{
            index--;
        }
    }
    res[index] = '\0';
    return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值