Leetcoede编程基础0到1——1768. 交替合并字符串& 389. 找不同&28. 找出字符串中第一个匹配项的下标 & 242.有效的字母异位词

1768. 交替合并字符串

题目描述:

给你两个字符串 word1word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。

返回 合并后的字符串

输入输出实例:

示例 1:

复制代码
输入:word1 = "abc", word2 = "pqr"
输出:"apbqcr"
解释:字符串合并情况如下所示:
word1:  a   b   c
word2:    p   q   r
合并后:  a p b q c r

示例 2:

复制代码
输入:word1 = "ab", word2 = "pqrs"
输出:"apbqrs"
解释:注意,word2 比 word1 长,"rs" 需要追加到合并后字符串的末尾。
word1:  a   b 
word2:    p   q   r   s
合并后:  a p b q   r   s

示例 3:

复制代码
输入:word1 = "abcd", word2 = "pq"
输出:"apbqcd"
解释:注意,word1 比 word2 长,"cd" 需要追加到合并后字符串的末尾。
word1:  a   b   c   d
word2:    p   q 
合并后:  a p b q c   d

提示:

  • 1 <= word1.length, word2.length <= 100
  • word1word2 由小写英文字母组成

实现原理:

函数 mergeAlternately

  1. 获取字符串长度 :使用 strlen 函数获取 word1word2 的长度。
  2. 分配内存 :为结果字符串 ans 分配内存,大小为 n+m+1,其中 nm 分别是 word1word2 的长度,+1 是为了存储字符串结束符 \0
  3. 交替合并 :使用一个循环遍历 word1word2,每次循环中,如果 word1 还有字符,将其添加到 ans 中,然后是 word2 的字符。如果其中一个字符串已经遍历完,则只添加另一个字符串的字符。
  4. 添加结束符 :在结果字符串末尾添加字符串结束符 \0
  5. 返回结果 :返回合并后的字符串 ans

main 函数

  1. 定义字符数组 :定义两个字符数组 word1word2,分别存储待合并的字符串。
  2. 调用函数 :调用 mergeAlternately 函数,将 word1word2 作为参数传入,并打印合并后的结果。
  3. 返回值:返回0,表示程序正常结束。

完整代码:

#include <stdio.h>
#include <string.h>
// 合并两个字符串
char * mergeAlternately(char * word1, char * word2){
    // 获取word1的长度
    int n=strlen(word1);
    // 获取word2的长度
    int m=strlen(word2);
    // 为结果字符串分配内存空间
    char* ans=malloc(((n+m+1))*sizeof(char));
    // 初始化结果字符串的索引
    int k=0;
    // 遍历word1和word2
    for(int i=0;i<n||i<m;i++){
        // 如果word1还有字符,将其添加到结果字符串中
        if(i<n){
            ans[k++]=word1[i];
        }
        // 如果word2还有字符,将其添加到结果字符串中
        if(i<m){
            ans[k++]=word2[i];
        }}
    // 在结果字符串末尾添加字符串结束符
    ans[k]='\0';
    // 返回结果字符串
    return ans;

}
int main(){
    // 定义两个字符数组
    char word1[]="acde";
    char word2[]="gehf";
    // 定义一个函数指针,指向mergeAlternately函数
    char * mergeAlternately(char * word1, char * word2);
    // 调用mergeAlternately函数,并打印结果
    printf("%s",mergeAlternately(word1,word2));
    return 0;
}

389.找不同

题目描述:

给定两个字符串 st ,它们只包含小写字母。

字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。

请找出在 t 中被添加的字母。

输入输出实例;

示例 1:

输入:s = "abcd", t = "abcde"

输出:"e"

解释:'e' 是那个被添加的字母。

示例 2:

输入:s = "", t = "y"

输出:"y"

提示:

0 <= s.length <= 1000

t.length == s.length + 1

s 和 t 只包含小写字母

实现原理:

定义和初始化数组:首先定义一个大小为26的整型数组cnt,用于记录每个字母(假设只考虑小写字母)在字符串s中出现的次数。数组cnt的索引对应字母a到z。

遍历字符串s:通过遍历字符串s,将每个字符出现的次数记录在数组cnt中。具体操作是将字符转换为对应的数组索引(通过减去字符'a'),然后增加该索引位置的值。

遍历字符串t:接着遍历字符串t,减少数组cnt中对应字符的计数。如果在减少计数时发现某个字符的计数小于0,说明该字符在字符串t中比在字符串s中多出现了一次,因此返回该字符。

返回结果:如果遍历完字符串t后没有发现计数小于0的字符,说明两个字符串完全相同,此时返回空格字符' '。

完整代码:

#include<stdio.h>
#include<string.h>
 
// 定义一个函数,用于找出两个字符串之间的不同字符
char findTheDifference(char* s, char* t) {
    // 定义一个数组,用于记录每个字符出现的次数
    int cnt[26];
    // 将数组初始化为0
    memset(cnt,0,sizeof(cnt));
    // 获取两个字符串的长度
    int n=strlen(s),m=strlen(t);
    // 遍历字符串s,记录每个字符出现的次数
    for(int i=0;i<n;i++){
        cnt[s[i]-'a']++;
    }
    // 遍历字符串t,减少每个字符出现的次数
    for(int i=0;i<m;i++){
        cnt[t[i]-'a']--;
        // 如果某个字符在t中出现的次数比在s中多,则返回该字符
        if(cnt[t[i]-'a']<0){
            return t[i];
        }
    }
    // 如果没有找到不同的字符,则返回空格
    return ' ';
}
 
int main(){
    // 定义两个字符串
    char s[]="abcd";
    char t[]="adebc";
    // 调用函数,找出两个字符串之间的不同字符,并打印出来
    printf("%c",findTheDifference(s,t));
    return 0;
}

28. 找出字符串中第一个匹配项的下标

题目描述

给你两个字符串 haystackneedle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1

输入输出实例:

示例 1:

复制代码
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

示例 2:

复制代码
输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。

提示:

  • 1 <= haystack.length, needle.length <= 104
  • haystackneedle 仅由小写英文字符组成

解法:

1.BF算法

实现原理

  1. 计算字符串长度 :首先,使用strlen函数计算haystackneedle的长度,分别存储在变量nm中。
  2. 遍历haystack :使用一个for循环遍历haystack,从第一个字符开始,直到haystack的长度减去needle的长度。
  3. 匹配检查 :在每次循环中,使用另一个for循环检查haystack中从当前位置开始的子字符串是否与needle匹配。如果匹配,则设置一个布尔变量flagtrue
  4. 返回结果 :如果在检查过程中发现flag仍为true,则返回当前的位置i。如果循环结束后仍未找到匹配,则返回-1。

完整代码:

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// 在字符串 haystack 中查找字符串 needle 的第一次出现的位置
int strStr(char* haystack, char* needle) {
  // 获取字符串 haystack 和 needle 的长度
  int n=strlen(haystack),m=strlen(needle);
    // 遍历字符串 haystack
    for(int i=0;i+m<=n;i++){
        // 设置标志位 flag 为 true
        bool flag=true;
         // 遍历字符串 needle
         for(int j=0;j<m;j++)
    {
        // 如果 haystack 和 needle 对应位置的字符不相等,则将 flag 设置为 false,并跳出循环
        if(haystack[i+j]!=needle[j])
       {flag=false;
        break;
        } 
    }
    // 如果 flag 为 true,则返回 haystack 中 needle 的第一次出现的位置
    if(flag){
    return i;
    }
    }
    // 如果 haystack 中没有 needle,则返回 -1
    return -1;
}   

int main(){
    // 定义字符串 haystack 和 needle
    char haystack[]="a";
    char needle[]="a";
    // 调用 strStr 函数,获取 needle 在 haystack 中的第一次出现的位置
    int ans=strStr(haystack,needle);
    // 输出结果
    printf("%d",ans);
    return 0;
}

2.kmp算法

实现原理

  1. 计算部分匹配表(Partial Match Table)

    • 首先计算 needle 的部分匹配表,这个表用于记录 needle 中每个位置之前的子串的最长相等前后缀的长度。
    • 部分匹配表 pi 的长度与 needle 的长度相同,pi[i] 表示 needle[0...i] 的最长相等前后缀的长度。
  2. 字符串匹配

    • 使用两个指针 ij,分别指向 haystackneedle 的当前字符。
    • haystack[i]needle[j] 匹配时,j 增加,i 也增加。
    • haystack[i]needle[j] 不匹配时,j 回退到 pi[j-1] 的位置,即 j = pi[j-1]
    • 如果 j 达到 needle 的长度,说明找到了匹配,返回 i - needle.length + 1

完整代码:

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

// 在字符串 haystack 中查找字符串 needle 的第一次出现的位置
int strStr(char* haystack, char* needle) {
    // 获取字符串 haystack 和 needle 的长度
    int n = strlen(haystack), m = strlen(needle);
    // 如果 needle 为空字符串,则返回 0
    if (m == 0) {
        return 0;
    }
    // 定义一个数组 pi,用于存储 needle 的部分匹配值
    int pi[m];
    // 初始化 pi 数组的第一个元素为 0
    pi[0] = 0;
    // 遍历 needle,计算部分匹配值
    for (int i = 1, j = 0; i < m; i++) {
        // 如果当前字符不匹配,则回退到上一个部分匹配值的位置
        while (j > 0 && needle[i] != needle[j]) {
            j = pi[j - 1];
        }
        // 如果当前字符匹配,则部分匹配值加 1
        if (needle[i] == needle[j]) {
            j++;
        }
        // 将部分匹配值存储到 pi 数组中
        pi[i] = j;
    }
    // 遍历 haystack,查找 needle 的第一次出现位置
    for (int i = 0, j = 0; i < n; i++) {
        // 如果当前字符不匹配,则回退到上一个部分匹配值的位置
        while (j > 0 && haystack[i] != needle[j]) {
            j = pi[j - 1];
        }
        // 如果当前字符匹配,则部分匹配值加 1
        if (haystack[i] == needle[j]) {
            j++;
        }
        // 如果部分匹配值等于 needle 的长度,则返回 haystack 中 needle 的第一次出现位置
        if (j == m) {
            return i - m + 1;
        }
    }
    // 如果 haystack 中没有 needle,则返回 -1
    return -1;
}

int main() {
    // 定义字符串 haystack 和 needle
    char haystack[] = "a";
    char needle[] = "a";
    // 调用 strStr 函数,查找 needle 在 haystack 中的第一次出现位置
    int result = strStr(haystack, needle);
    // 输出结果
    printf("%d\n", result);
    return 0;
}

242.有效的字母异位词

题目描述:

给定两个字符串 st ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:st中每个字符出现的次数都相同,则称 st互为字母异位词。

输入输出实例:

示例 1:

复制代码
输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

复制代码
输入: s = "rat", t = "car"
输出: false

提示:

  • 1 <= s.length, t.length <= 5 * 104
  • st 仅包含小写字母

实现原理

  1. 计算部分匹配表(Partial Match Table)

    • 首先计算 needle 的部分匹配表,这个表用于记录 needle 中每个位置之前的子串的最长相等前后缀的长度。
    • 部分匹配表 pi 的长度与 needle 的长度相同,pi[i] 表示 needle[0...i] 的最长相等前后缀的长度。
  2. 字符串匹配

    • 使用两个指针 ij,分别指向 haystackneedle 的当前字符。
    • haystack[i]needle[j] 匹配时,j 增加,i 也增加。
    • haystack[i]needle[j] 不匹配时,j 回退到 pi[j-1] 的位置,即 j = pi[j-1]
    • 如果 j 达到 needle 的长度,说明找到了匹配,返回 i - needle.length + 1

完整代码:

#include <stdbool.h>
#include <stdio.h>
#include <string.h> // strcmp

// 比较函数,用于qsort排序
int cmp(const void* _a, const void* _b) {
    char a = *(char*)_a, b = *(char*)_b;
    return a - b;
}

// 判断两个字符串是否为字母异位词
bool isAnagram(char* s, char* t) {
    int len_s = strlen(s), len_t = strlen(t);
    // 如果两个字符串长度不相等,则不是字母异位词
    if (len_s != len_t) {
        return false;
    }
    // 对两个字符串进行排序
    qsort(s, len_s, sizeof(char), cmp);
    qsort(t, len_t, sizeof(char), cmp);
    // 如果排序后的字符串相等,则是字母异位词
    return strcmp(s, t) == 0;
}
int main() {
    char s[] = "anagram", t[] = "nagaram";
    printf("%d\n", isAnagram(s, t));
    return 0;
}

拓展:qsort函数

qsort函数是C语言标准库<stdlib.h>中的一个函数,用于对数组进行排序。它是一个非常高效且方便的内置排序工具,其内部实现通常基于快速排序算法,这使得它在处理大规模数据集时表现出非常高的效率。在使用qsort函数时,需要提供四个参数,分别是要排序的数组、数组中元素的个数、每个元素的大小(字节数),以及一个比较函数。下面将详细解释如何使用qsort函数:

包含头文件

头文件引入:使用qsort前,需要在代码文件中引入<stdlib.h>头文件。

函数格式及参数详解

数组名:要排序的数组名,即数组的起始地址。

元素个数:要排序的数组中的元素个数。

元素大小:数组中每个元素的大小(字节数),例如sizeof(int)、sizeof(double)等。

排序原则:通过一个自定义的比较函数来确定排序规则。这个函数需要返回三个可能的值:负值表示第一个参数应排在第二个之前,零表示相等,正值表示第一个参数应排在第二个之后。

比较函数详解

整型数组排序:对于整型数据,比较函数可以简单地通过减法确定排序顺序。例如,升序为return *(int*)a - *(int*)b;。

浮点数和字符串排序:对于这些类型,为了避免精度损失或正确比较字符串,建议使用大于、小于或等于运算符来决定返回值。

结构体排序:如果排序的对象是结构体,比较函数需要针对结构体中的特定字段进行比较,如按照年龄或名称排序。

典型用法示例

整数数组排序:

int values[] = { 88, 56, 100, 2, 25 };
int cmp(const void *a, const void *b) {
    return ( *(int*)a - *(int*)b );
}
qsort(values, 5, sizeof(int), cmp);

结构体数组排序:

struct In {
    int x;
    int y;
}s[100];
int cmp(const void *a, const void *b) {
    struct In *c = (struct In *)a;
    struct In *d = (struct In *)b;
    if(c->x != d->x) return c->x - d->x;
    return d->y - c->y;
}
qsort(s, 100, sizeof(s[0]), cmp);

此外,为了确保在使用qsort函数时能够获得最佳实践,以下是一些额外的提示和建议:

当排序的结构体或其他复杂类型时,确保比较函数正确地处理了所有可能的排序键。

考虑到qsort是一个不稳定的排序算法,如果需要稳定排序(即值相同的情况下保持原始顺序),则应考虑其他选项,如Merge Sort。

在处理大量数据时,注意内存使用和性能优化。尽管qsort非常高效,但在某些情况下,特定的排序算法可能会更适合特定的数据集或应用场景。

相关推荐
_WndProc14 分钟前
C++ 日志输出
开发语言·c++·算法
努力学习编程的伍大侠27 分钟前
基础排序算法
数据结构·c++·算法
XiaoLeisj1 小时前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
Jasmine_llq1 小时前
《 火星人 》
算法·青少年编程·c#
闻缺陷则喜何志丹1 小时前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
Lenyiin2 小时前
01.02、判定是否互为字符重排
算法·leetcode
鸽鸽程序猿2 小时前
【算法】【优选算法】宽搜(BFS)中队列的使用
算法·宽度优先·队列
Jackey_Song_Odd2 小时前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
Watermelo6172 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript