刷题 ------ 字符串

1.罗马数字转整数

在这里插入图片描述

  • 将字符所对应的ASCII码作为数组的索引,构造一个一个哈希表出来。
  • 然后比字符串中比较,如果当前的比下一个小,那么就减去当前的值
  • 否则就加上当前的值
int romanToInt(char* s)
{
    char* p = s;
    int sum = 0;
    int hash[26] = {0};

    hash['I' - 'A'] = 1;
    hash['V' - 'A'] = 5;
    hash['X' - 'A'] = 10;
    hash['L' - 'A'] = 50;
    hash['C' - 'A'] = 100;
    hash['D' - 'A'] = 500;
    hash['M' - 'A'] = 1000;

    while(*p != '\0')
    {
        int val = hash[*p - 'A'];

        if( p[1] != '\0' &&  val < hash[p[1] - 'A'])
        {
            sum -= val;
        }
        else
        {
            sum += val;
        }

        p++;
    }


    return sum;
}

2.最长公共前缀

在这里插入图片描述
该题主要的考察就是在于如何同时比较所有字符串中的各个元素

  • 外层的循环是循环字符串长度,而字符串长度取决于全部字符串中长度最小的,因为公共前缀,最大最多只能是里面长度最短的了。
  • 内层循环是循环有多少个字符串如果每个字符串都正常结束,那么循环变量一定是等于字符串个数的。否则就是有不一样的。
char* longestCommonPrefix(char** strs, int strsSize)
{
    int minlen  = 10000;
    int i,j;
    for (i = 0; i < strsSize; i++)
    {
        int len = strlen(strs[i]);
        if(len < minlen)
        {
            minlen = len;
        }
    }

    for (j = 0; j < minlen; j++)
    {

        //j 为不变的 挨个遍历第 j 个元素
        for (i = 1; i < strsSize; i++)
        {
            //发现有一个不一样就结束
            if(strs[i-1][j] != strs[i][j])
            {
                break;
            }
        }
        //如果 i != 总共字符串的个数,证明没有遍历完,中间肯定有不一样的,所有导致提前结束了。
        if(i != strsSize)
        {
            break;
        }
    }

    //就在当前不匹配的地方赋值上 '\0'
    strs[0][j] = '\0';
    return strs[0];
}


3. 有效的括号

在这里插入图片描述
运用栈可以很好的解决整个题


bool isValid(char * s)
{
    int len = strlen(s);
    char* stack = (char*)malloc(sizeof(char) * (len+1));
    char gettop = 0;    //栈顶元素
    int top = 0;        //栈指针

    while(*s != '\0')
    {
        //如果是左括号,那么就入栈
        if( *s == '(' || *s == '{' || *s == '[')
        {
            stack[++top] = *s;
            s++;
        }
        else
        {
            //如果栈为空,就证明刚的开始第一个就是右括号,如果是这样,就肯顶不能匹配上了
            if(top == 0)
            {
                return false;
            }
            else
            {
                //({()})
                //栈不为空,开始判断一下三种条件即可,有一个不匹配,直接返回false即可
                gettop = stack[top--];
                if((gettop == '(' && *s != ')') || gettop == '{' && *s != '}' || gettop == '[' && *s != ']')
                {
                    return false;
                }
                else
                {
                    //如果全部匹配,那么去找下一个
                    s++;
                }
            }

        }

    }

    //栈如果为空,肯定就是全部匹配完成的情况,如果还有元素,那么就是未匹配好的。
    return top == 0 ? true : false;
}

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

在这里插入图片描述
这是一个匹配字符串的问题
方法一:暴力双for即可解决

  • 去挨个遍历源字符串中的字符,如果发现个子字符串的第一个相同
  • 然后两个字符串挨个比较即可
int strStr(char* haystack, char* needle)
{   
    int i,j;
    i = j = 0;
    int len1 = strlen(haystack);
    int len2 = strlen(needle);
    
    //如果要找的比源来的小,直接返回即可
    if(len2 > len1)
    {
        return -1;
    }


    for (i = 0; i < len1; i++)
    {
        if(haystack[i] == needle[0])
        {

            for (j = 1; j < len2; j++)
            {
                if(haystack[i+j] != needle[j])
                {
                    break;
                }
            }

            if(j == len2)
            {
                return i;
            }
        }

    }


    return -1;
}

5. 最后一个单词的长度

在这里插入图片描述

  • 既然是找最后一个单词,那么直接求出字符串的长度,
  • 然后从后往前找即可
int lengthOfLastWord(char* s)
{   
    int len = strlen(s);
    int i;
    int ans = 0;
    for (i = len -1; i >= 0; i--)
    {
        //如果找到了空格,并且在此之前还找到了字母就意味着这个单词结束了
        if(s[i] == ' ' && ans != 0)
        {
            break;
        }
        //如果不等于空格长度增加
        if(s[i] != ' ')
        {
            ans++;
        }
    }


    return ans;

}

6.二进制求和

在这里插入图片描述

  • 利用二进制的加法即可,
  • 我们创建一个数组,然后将所给的2个数组,从后往前依次加即可,
  • 加的时候要注意一个进位的问题
//需要进位
        if(carry == 2)
        {
            ans[index++] = '0';
            carry /= 2;
        }
        else if(carry > 2)
        { 
            ans[index++] = '1';
            carry /= 2;
        }
        else if(carry == 0)
        {
            ans[index++] = '0';
        }
        else
        {
            ans[index++] = '1';
            carry = 0;
        }
  • 最后将字符串逆序回去即可

void Reverse(char* s)
{
    int i = 0,j = strlen(s) - 1;

    while (i < j)
    {
        char tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;

        i++;
        j--;
    }

}

char* addBinary(char* a, char* b)
{
    int lena = strlen(a);
    int lenb = strlen(b);
    int i,j,carry;
    i = lena - 1;   // a 的下标
    j = lenb - 1;   // b 的下标
    carry = 0;      // 进位
    int maxlen = lena > lenb ? lena : lenb;
    char* ans = (char*)malloc(sizeof(char) * (maxlen + 2));      //需要进位和以及后面补'\0'
    int index = 0;

    while(i >= 0 || j >= 0 || carry != 0)
    {
        // a 里面还有字符
        if(i >= 0)
        {
            carry += a[i--] - '0';  //a[i] - '0' 就是当前的字符转换为10进制 '1' - '0' = 1  '0' - '0' = 0 
        }

        // b 里面还有字符
        if(j >= 0)
        {
            carry += b[j--] - '0';
        }
        
        //需要进位
        if(carry == 2)
        {
            ans[index++] = '0';
            carry /= 2;
        }
        else if(carry > 2)
        { 
            ans[index++] = '1';
            carry /= 2;
        }
        else if(carry == 0)
        {
            ans[index++] = '0';
        }
        else
        {
            ans[index++] = '1';
            carry = 0;
        }

    }
    ans[index] = '\0';
    Reverse(ans);
    
    return ans;
}

7.验证回文字符串

在这里插入图片描述

  • 首先将字符串中的所有不是字母和数字的字符去除掉
  • 接着双指针判断字符串是否回文即可
//清除字符串中的符号 并且将所有大写转化为小写
char* AdjustStr(char* s)
{
    char* newstr = (char*)malloc(sizeof(char) * (strlen(s) + 1));
    int index = 0;

    while(*s != '\0')
    {
        //是26个字母
        if((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') || (*s) >= '0' && (*s) <= '9')
        {
            //转换为小写全部
            newstr[index++] = tolower(*s);
        }
        s++;
    }
    newstr[index] = '\0';
    return newstr;
}


bool isPalindrome(char* s)
{
    s = AdjustStr(s);
    int i = 0, j = strlen(s) - 1;
    while(i < j)
    {
        if(s[i] != s[j])
        {
            return false;
        }
        i++;
        j--;
    }

    return true;
}

8. Excel表列名称

在这里插入图片描述


void Reverse(char* s,int len)
{
    int i = 0,j = len -1;
    while(i < j)
    {
        char tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
        i++;
        j--;
    }
}

char* convertToTitle(int columnNumber)
{
    char* ans = (char*)malloc(sizeof(char) * 10);
    int index = 0;
    while(columnNumber > 0)
    {
        columnNumber--;
        ans[index++] = columnNumber % 26 + 'A';
        columnNumber /= 26;
    }
    
    ans[index] = '\0';
    Reverse(ans,strlen(ans));

    return ans;
}


9. Excel表列序号

在这里插入图片描述

  • 和上题一样,进制转换而已,把他想象成一个26进制即可
int titleToNumber(char* columnTitle)
{
    int n = strlen(columnTitle);    //位数
    int sum = 0;

    while(*columnTitle != '\0')
    {
        //65 是 'A' 64 是@        也可写成64
        sum += ((*columnTitle) - '@') * pow(26,n-1);
        columnTitle++;
        n--;
    }

    return sum;
}

10. 同构字符串

在这里插入图片描述

  • 首先构造两个哈希表出来,将第一个字符串中的每一个字符所对应第二个字符串中的字符
  • 如果出现过,判断第一次映射的和第二次出现的需要映射的是否相等即可。
  • 最后将第二个字符串重复前面两步即可。

bool isIsomorphic(char* s, char* t)
{
    int len = strlen(s);
    char* maps[256] = {0};
    char* mapt[256] = {0};
    int i = 0;

    //用s映射t
    for (i = 0 ; i < len; i++)
    {
        if(maps[s[i]] == 0)
        {
            maps[s[i]] = t[i];
        }

        if(maps[s[i]] != t[i])
        {
            return false;
        }

    }

    //用t隐射s
    for (i = 0; i < len; i++)
    {
        if(mapt[t[i]] == 0)
        {
            mapt[t[i]] = s[i];
        }


        if(mapt[t[i]] != s[i])
        {
            return false;
        }

    }

    return true;
}

11.有效的字母异位词

在这里插入图片描述
这道题的意思就是:两个字符串中,每个单词出现的次数是否和另一个字符串中出现的次数相同。

  • 构造两个哈希表,分别记录s和t两个字符串中单词出现的数量
  • 然后对哈希表进行遍历,看看是否对应相等

bool isAnagram(char* s, char* t)
{
    int maps[27] = {0};
    int mapt[27] = {0};
    int i,lens = strlen(s),lent = strlen(t);

    if(lens != lent)
    {
        return false;
    }

    for (i = 0; i < lens; i++)
    {
        maps[s[i] - 'a' + 1]++;
        mapt[t[i] - 'a' + 1]++;
    }

    for (i = 0; i < 26; i++)
    {
        if(maps[i] != mapt[i])
        {
            return false;
        }
    }

    return true;
}

12.单词规律

在这里插入图片描述
这道题和前面的同构字符串是一种类型的题,同样是构造两个哈希表,对其分别进行映射。

  • 第一个哈希表好弄,keys可以直接用ASSIC码值充当,一个数组即可
  • 第二个哈希表就难弄了,因为它的关键字是字符串,所以我这边是另外构造了一个结构出来的。

下面是我的解法,代码有点长,空间房费也有点大。但是时间快

#define MAX_SIZE 1000


typedef struct
{
    char* keys;
    char val;
}Map;

typedef struct
{
    Map Box[MAX_SIZE];
    int size;
}Hash;

//将一句话转化成各个字符串 并且用len 返回新的长度
char** ChangeStr(char* s, int* len)
{
    char** newstr = (char**)malloc(sizeof(char*) * (*len));
    int i, index = 0, size = 0;;

    for (i = 0; i < *len; i++)
    {
        newstr[size] = (char*)malloc(sizeof(char) * MAX_SIZE);
        while (s[i] != ' ' && s[i] != '\0')
        {
            newstr[size][index++] = s[i++];
        }
        newstr[size++][index] = '\0';
        index = 0;
    }
    *len = size;
    return newstr;
}

//在哈希表中关键字是否有该字符串  如果有返回 下标 否则返回 -1
int FindHash(Hash m, char* cur)
{
    int i;
    for (i = 0; i < m.size; i++)
    {
        if (strcmp(m.Box[i].keys, cur) == 0)
        {
            return i;
        }
    }

    return -1;
}

//初始化
void InitHash(Hash* m, int size)
{
    m->size = size;
    int i;
    for (i = 0; i < m->size; i++)
    {
        m->Box[i].keys = (char*)malloc(sizeof(char) * MAX_SIZE);
    }
}


bool wordPattern(char* pattern, char* s)
{
    int lenp = strlen(pattern);
    int lens = strlen(s);
    char** tmp = ChangeStr(s, &lens);

    //长度不同直接返回false
    if (lenp != lens)
    {
        return false;
    }

    char** mapstr = (char**)calloc(26, sizeof(char*));

    int i;
	//字母作为关键字,字符串作为值
    for (i = 0; i < lenp; i++)
    {
        //如果p中的当前字母没有映射所对应的单词,那么映射单词
        if (mapstr[pattern[i] - 'a'] == 0)
        {
            mapstr[pattern[i] - 'a'] = (char*)malloc(sizeof(char) * MAX_SIZE);
            strcpy(mapstr[pattern[i] - 'a'], tmp[i]);
        }

        //如果p中当前字母所映射的单词,和新单词不同,那么证明错误
        if (strcmp(tmp[i], mapstr[pattern[i] - 'a']) != 0)
        {
            return false;
        }
    }

    //字符串作为关键字,值为字母
    Hash mapalp;
    InitHash(&mapalp,lens);

    for (i = 0; i < lenp; i++)
    {
        int index = FindHash(mapalp, tmp[i]);
        //去哈希表中找该字符串是否由对应的单词
        if (index == -1)    //如果没有,那么插入
        {
            strcpy(mapalp.Box[i].keys, tmp[i]);
            mapalp.Box[i].val = pattern[i];
        }
        else
        {
            if (mapalp.Box[index].val != pattern[i])
            {
                return false;
            }
        }
       

    }

    return true;
}

在这里插入图片描述

13. 反转字符串

在这里插入图片描述

  • 额。。。。
  • 双指针,前后走
void reverseString(char* s, int sSize){
   int i = 0, j = sSize - 1;
   while (i < j)
   {
       int temp = s[i];
       s[i++] = s[j];
       s[j--] = temp;
   }
}

14. 反转字符串的中元音字母

在这里插入图片描述

  • 找到原因字母,
  • 然后交换位置
int vowel(char c)
{
    if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
        c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
      {
             return 1;
       }
    else
    {
    	return 0;
    }
}

char * reverseVowels(char * s){
    int i = 0, j = strlen(s) - 1;
    while(i < j){
        while(i < j && !vowel(s[i]))
        {
            i++;
        }
        while(i < j && !vowel(s[j]))
        {
            j--;
        }

        char t = s[i];
        s[i] = s[j];
        s[j] = t;
        i++;
        j--;
    }
    return s;
}

15.救赎金


该题的题意就是让你在magazine字符串中的所有字母,是否可以构造ransownote的字符串

  • 构造一个哈希表,统计一下第二个字符串中各个字母共有多少个
  • 然后在第一个字符串中去遍历,减去,如果小于0就说明多出来了。
bool canConstruct(char* ransomNote, char* magazine)
{
    //创建一个哈希表,记录magazine 里面有多少字母可以用
    int map[26] = {0};
    int i,lenr = strlen(ransomNote), lenm = strlen(magazine);
    if(lenr > lenm)
    {
        return false;
    }

    for (i = 0; i < lenm; i++)
    {
        map[magazine[i] - 'a']++;
    }

    for (i = 0; i < 26; i++)
    {
        printf("%d ",map[i]);
    }
    
    for (i = 0; i < lenr; i++)
    {
        map[ransomNote[i] - 'a']--;
        if(map[ransomNote[i] - 'a'] < 0)
        {
            return false;
        }
    }
    
    return true;
}

16.字符串中的第一个唯一字符

在这里插入图片描述

  • 构造一个哈希表出来,记录每个字符出现的次数
  • 然后在此遍历该字符串,去哈希表中去查看,自己出现了几次,如果出现了1次,那么就是它了
  • 切记不可以直接遍历哈希表,看谁出现1次,因为那样子,保证不了题目中所说的顺序
int firstUniqChar(char* s)
{
    int map[26] = {0};
    int len = strlen(s);
    int i;

    for (i = 0; i < len; i++)
    {
        map[s[i] - 'a']++;
    }

    //在遍历依次字符串
    for (i = 0; i < len; i++)
    {
        if (map[s[i] - 'a'] == 1)
        {
            return i;
        }
    }

    //error
    //如果遍历哈希表的话会出现先后的问题
    // for (i = 0; i < 26; i++)
    // {
    //     if(map[i] == 1)
    //     {
    //         return i;
    //     }
    // }

    return -1;
}

17.找不同

在这里插入图片描述
该题的意思就是看一个字符串比另一个字符串多出了哪一个字符

  • 构造两个哈希表出来
  • 分别遍历两个字符串,是哈希表完整
  • 接着比较哈希表是否相同,不同的位置,就是多出来的那个字符。
char findTheDifference(char* s, char* t)
{
    int maps[26] = {0};
    int mapt[26] = {0};
    int i,lens = strlen(s),lent = strlen(t);

    //构造两个字符串的哈希表
    for (i = 0; i < lent; i++)
    {
        if(i < lens)
        {
            maps[s[i] - 'a']++;
        }
        mapt[t[i] - 'a']++;
    }
    for (i = 0; i < 26; i++)
    {
        if(maps[i] != mapt[i])
        {
            return i + 'a';
            break;
        }
    }
    return ' ';
}

18. 判断子序列

在这里插入图片描述
s是否是t的子序列,切记注意是有顺序的,题目中最后也举出了例子
双指针

  • 用两个指针,分别指向两个字符串
  • 如果相等,那么就同时向后走,
  • 如果不相等,那么只有t中的向后走。
  • 当其中有一个走完的时候,就可以结束了
  • 如果 s 中的走完 证明一定找到了此字符串
  • 否则就是没找到
bool isSubsequence(char* s, char* t)
{
    int i = 0,j = 0;
    int lens = strlen(s);
    int lent = strlen(t);


    while(i < lens && j < lent )
    {
        if(s[i] == t[j])
        {
            i++;
            j++;
        }
        else
        {
            j++;
        }
    }

    if(i == lens)
    {
        return true;
    }
    else
    {
        return false;
    }
}

19.最长回文子字符串

在这里插入图片描述

  • 首先构造一个哈希表出来
  • 统计每个字母出现的次数
  • 如果是偶数次,则该字母一定可以构成回文
  • 如果是奇数次,那么该字母的 n - 1 就一定是偶数了
  • 还要要注意的就是单独出现一次的那一个字母得加进去

int longestPalindrome(char * s)
{
    int map[52] = {0};
    int i,len = strlen(s);
    int ans = 0;
    int flag = 0; // 代表出现一次的字母
    //记录每个字母出现的次数
    for (i = 0; i < len; i++)
    {
        if(s[i] >= 'a' && s[i] <= 'z')
        {
            map[s[i] - 'a']++;
        }
        else
        {
            map[s[i] - 'A' + 26]++;
        }
    }

    for (i = 0; i < 52; i++)
    {
        //如果出现偶数次,那么一定都能构成回文
        if( map[i] > 0 && map[i] % 2 == 0 )
        {
            ans += map[i];
        }

        //如果出现奇数次,把他前  n - 1 次一定是偶数
        if(map[i] > 0 && map[i] % 2 != 0)
        {
            ans += map[i]-1;
            flag = 1;
        }
    }
    
    if(flag == 1)
    {
        ans += 1;
    }

    return ans;
}


20.Fizz Buzz

在这里插入图片描述
判断是否是3 5 15 的倍数即可

	char ** fizzBuzz(int n, int* returnSize){
    char ** answer = (char **)malloc((sizeof(char *) * (n))); 
    char * arr = (char *)malloc(sizeof(char) * n *9);
    *returnSize = n; 
    for(int i=0;i<n;i++)
    {
        answer[i] = &arr[9*i];
    }
    for(int i = 1; i <= n; i++)
    {
        if(i % 3 == 0 && i % 5 == 0)
        {
            strcpy(answer[i-1],"FizzBuzz");
        }
        else if(i % 3 == 0)
        {
            strcpy(answer[i-1],"Fizz");

        }
        else if(i % 5 == 0)
        {
            strcpy(answer[i-1],"Buzz");
        }
        else
        {
            sprintf(answer[i-1],"%d",i);
        }
    }
    return answer;
}

这道题题有问题!!!!!题目中说索引从1开始,完了我就从1开始,结果一直错,内存问题,折磨我半小时,看评论才知道题目有问题!

21.字符串相加

在这里插入图片描述
这道题和该目录中过的第6题也是leetcode里的67题二进制求和是一样的,这个是10进制求和而已

  • 唯一就是在判断那个进位变量的时候不同,
  • 还要注意在ASCII码中没有十几这样的数字,所以在求模的时候得注意.
  • 依旧和前面的二进制求和代码逻辑是一样的,从后往前加,加到ans中最后逆序。
void Reverse(char* s,int len)
{
    int i = 0,j = len -1;
    while(i < j)
    {
        char tmp = s[i];
        s[i++] = s[j];
        s[j--] = tmp;
    }

}


char * addStrings(char * num1, char * num2)
{
    int i,j,len1 = strlen(num1),len2 = strlen(num2);
    i = len1 - 1;
    j = len2 - 1;
    int maxlen = len1 > len2? len1 : len2;
    char* ans = (char*)malloc(sizeof(char) * (maxlen + 2)); //需要进位和补'\0'
    int index = 0,tmp = 0;
    while(i >= 0 || j >= 0 || tmp != 0)
    {
        if(i >= 0)
        {
            tmp += num1[i] - '0';
        }

        if(j >= 0)
        {
            tmp += num2[j] - '0';
        }

        //不需要进位
        if(tmp < 10)
        {
            ans[index++] = tmp + '0';
            tmp = 0;
        }
        else
        {
            ans[index++] = (tmp%10) + '0';
            //ans[index++] = (tmp + '0') % 10;  Error
            tmp = 1;

        }
        i--;
        j--;
    }

    ans[index] = '\0';
    Reverse(ans,index);
    return ans;
}

22.字符串中的单词数

在这里插入图片描述
因为每一个句子是由空格分隔开的,所以,只要当前的不是空格,而自己前面的那一个是空格,就证明新的单词开始了。但是一定要注意字符串的第一个字母,运用i-1会出现越界,再加一个条件即可

int countSegments(char * s)
{
    int count = 0,i,len = strlen(s);

    for (i = 0; i < len; i++)
    {
        if( (i == 0 || s[i-1] == ' ') && s[i] != ' ')
        {
            count++;
        }
    }


    return count;
}

23.密钥格式化

在这里插入图片描述
思路是从后往前

  • 从后面把每一段都设置成k次就好了
  • 最后逆序即可

void Reverse(char* s,int len)
{
    int i = 0,j = len - 1;

    while(i < j)
    {
        char tmp = s[i];
        s[i++] = s[j];
        s[j--] = tmp;
    }
}

char* licenseKeyFormatting(char* s, int k)
{
    int count = 0, i;
    int len = strlen(s);
    char* ans = (char*)malloc(sizeof(char) * (len*2));
    int index = 0;

    int num = 0;        //记录当前这一段有多少个字母了
    char ch;

    for (i = len -1; i >= 0;i--)
    {
        ch = s[i];

        if(ch == '-')
        {
            continue;
        }
        else
        {
            //小写转大写
            if(ch >= 'a' && ch <= 'z')
            {
                ch  = ch - 'a' + 'A';
            }

            //一段完成
            if(num >= k)
            {
                ans[index++] = '-';
                num = 0;
            }

            ans[index++] = ch;
            num++;
        }
    }
    ans[index] = '\0';
    
    Reverse(ans,index);
    return ans;
}

24.键盘行

在这里插入图片描述

  • 首先构造一个哈希表,记录26个英文字母在哪一行
  • 然后去遍历每个单词,去哈希表中查,看看其中字母是否在同一行即可。

一定要注意,开辟空间的时候要注意’\0’所以要多开辟一个空间!!!!!!!

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


//当前的val是那一行的英文字母
int CheckRow(int val)
{
    char* s1 = "qwertyuiop";
    char* s2 = "asdfghjkl";
    char* s3 =  "zxcvbnm";
    int i;
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    int len3 = strlen(s3);


    char ch = val;
    for (i = 0; i < len1; i++)
    {
        if(ch == s1[i])
        {
            return 1;
        }
    }

    for (i = 0; i < len2; i++)
    {
        if(ch == s2[i])
        {
            return 2;
        }
    }

    for (i = 0; i < len3; i++)
    {
        if(ch == s3[i])
        {
            return 3;
        }
    }
    
    return 0;
}

char ** findWords(char ** words, int wordsSize, int* returnSize)
{
   int map[26] = {0};
   char** ans = (char**)malloc(sizeof(char*) * wordsSize);
   *returnSize = 0;
    int i;
    int row;

    //构造哈希表得出26个英文字母在哪一行
    for (i = 97; i <= 122; i++)
    {
        row = CheckRow(i);
        map[i - 'a'] = row;
    }

    for (i = 0; i < wordsSize; i++)
    {
        int j;
        int k = strlen(words[i]);
        //去遍历每个字母
        for (j = 1; j < k; j++)
        {
            char prev = tolower(words[i][j - 1]);
            char cur = tolower(words[i][j]);

            if(map[prev - 'a'] != map[cur - 'a'])
            {
                break;
            }
        }
        //如果全部比较完 j == k 就证明这一个单词里面的所有字母都在同一行
        if(j == k)
        {
            ans[(*returnSize)] = (char*)malloc(sizeof(char) * (k+1));
            strcpy(ans[(*returnSize)],words[i]);
            (*returnSize)++;
        }

    }

    return ans;
}

25.检测大写字母

在这里插入图片描述
看题目可以知道,后面所有的字母,都必须和第二个字母的大小写相同,只有这样子才是正确的。另外我们还需要判断,如果当首字母是小写,第二个也必须是小写。

bool detectCapitalUse(char* word)
{
    int i,len = strlen(word);

    if(len == 1)
    {
        return true;
    }

    for (i = 2; i < len; i++)
    {
        //后面的都必须和第二个相等
        if(isupper(word[i]) != isupper(word[1]))
        {
            return  false;
        }
    }

    //如果第一个是小写,那么第二个必须也是小写
    if(islower(word[0]) && isupper(word[1]))
    {
        return false;
    }

    return true;
}

26.最长特殊序列

在这里插入图片描述
绷不住了,真绷不住了!!!!!

int findLUSlength(char* a, char* b)
{
    int lena = strlen(a),lenb = strlen(b);
    if(lena != lenb)
    {
        return lena > lenb ? lena : lenb;
    }

    if(strcmp(a,b) == 0)
    {
        return -1;
    }
    return lena;
}

好好好好!
在这里插入图片描述

27.反转字符串||

在这里插入图片描述


char* reverseStr(char* s, int k)
{
    int i, len = strlen(s);

    for (i = 0; i < len; i += (k*2))
    {
        k = i + k > len ? len - i : k;
        int begin = i;
        int end = i + k - 1;

        while(begin < end)
        {
            char tmp = s[begin];
            s[begin++] = s[end];
            s[end--] = tmp;
        }
    }

    return s;

}

28.学生出勤记录

在这里插入图片描述
这道题的意思就是说,如果整个字符串中出现两个A 或者是三个连在一起的L那么就返回false 否则 返回true

  • 我们只需要对字符串进行遍历,如果碰到A那么计数,
  • 碰到L进行判断他的后几个是否也是。

方法一:暴力枚举
直接对该数组进行一个遍历。

bool checkRecord(char* s)
{
    int i,len = strlen(s);
    int numA = 0;
    int numL = 0;

    for (i = 0; i < len; i++)
    {
        if(s[i] == 'A')
        {
            numA++;
            if(numA == 2)
            {
                return false;
            }
        }

        if(s[i] == 'L')
        {
            numL = 0;
            int j;
            for (j = i; j < len && s[j] == 'L'; j++)
            {
                numL++;
                if(numL == 3)
                {
                    return false;
                }
            }
        }
    }

    return true;
}

方法二: 这种方法相对于上面的,在判断L的时候改成了两个if语句,时间上快了不。

bool checkRecord(char * s)
{
    int numA = 0;
    int slen = strlen(s);
    for(int i = 0; i < slen; i++)
    {
        if(s[i]  == 'A')
        {
            numA++;
            if(numA >= 2)
            {
                return false;
            }
        }
        else
        {
            if(i + 2 < slen)
            {
                if(s[i] == 'L' && s[i + 1] == 'L' && s[i+2] == 'L')
                    return false;
            }
        }
    }
    
        
    return true;
}

29.反转字符串中的单词|||

在这里插入图片描述
反转字符串都会,这里就是把大字符串拆分成小的字符串就好了。

方法一: 这是我第一时间想到的,就是求出当前单词的长度,然后反转整个单词。

  • 求出当前单词的长度,然后进行反转
  • 将i 变成下一个单词的开头。
int MyStrlen(char*s)
{
    int count = 0;
    while(*s != ' ' && *s != '\0')
    {
        count++;
        s++;
    }

    return count;
}


char* reverseWords(char* s)
{
    int i = 0,len = strlen(s);

    while(i < len)
    {
        int curlen = MyStrlen(&s[i]);
        int left = i;
        int right = left + curlen - 1;

        while (left < right)
        {
            char tmp = s[left];
            s[left++] = s[right];
            s[right--] = tmp;
        }

        i =  i + curlen + 1;
    }

    return s;
}

方法2: 看了别人题解后,其实思路整体也就是这个思路,只是人家的更加的简洁?效率更快?


char* reverseWords(char* s)
{
    int i = 0,j,len = strlen(s);
    int left,right;
    while(i < len)
    {
        j = i;

        while(s[j] != ' ' && j < len)
        {
            j++;
        }
        left = i;
        right = j - 1;

        while(left < right)
        {
            char tmp = s[left]; 
            s[left++] = s[right];
            s[right--] = tmp;
        }

        i = j + 1;
    }

    return s;
}

30.两个列表的最小索引总和

在这里插入图片描述
没什么技巧,我这里就是暴力求解的。超过5%的人。。。就先这样吧

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
char** findRestaurant(char** list1, int list1Size, char** list2, int list2Size, int* returnSize)
{

    int maxsize = list1Size > list2Size ? list1Size : list2Size;
    char** ans = (char**)malloc(sizeof(char*) * maxsize);
    int i,j,minindexsum = 9999;
    *returnSize = 0;
    
    for (i = 0; i < list1Size; i++)
    {

        for (j = 0; j < list2Size; j++)
        {
            //相等
            if(strcmp(list1[i],list2[j]) == 0)
            {
                //如果相同则继续录入
                if((i + j == minindexsum) || minindexsum == 9999)
                {
                    minindexsum = i + j;
                    ans[*returnSize] = (char*)malloc(sizeof(char) * (strlen(list1[i]) + 1));
                    strcpy(ans[(*returnSize)++],list1[i]);
                    continue;
                }

                if(i + j < minindexsum)
                {
                    minindexsum = i + j;
                    strcpy(ans[(*returnSize)-1],list1[i]);
                }
               
            }
        }
    }

    return ans;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值