《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)

字符/回文串/公共前缀/单词

520. 检测大写字母
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第1张图片

算法思想:
思路一:
1.首先判断第一个元素是否为大写字母,初始化ishave为false表示不含有大写字母,若有将其置为true
2.若第一个字母为大写字母
下一个字母为大写字母,那么接下来每个字母只能为大写字母
下一个字母为小写字母,那么接下来每个字母只能为小写字母
若第一个字母不为大写字母 接下来每个字符只能为空或小写字母
思路二:
思路二:
1.直接设置计数器up统计大写字母的个数
若未出现大写字母 遍历完成后则直接返回true
若大写字母个数小于等于下标时,则说明中间存在小写字母 直接返回false
2.结尾判断是否大写字母的个数等于字符串长度或小于等于1,若是返回true 否则返回false(说明存在末尾存在小写字符)

思路一(自己的想法)
bool detectCapitalUse(char * str){
     
    int i = 0;
    bool ishave = (str[i] >= 'A' && str[i] <='Z') ? true:false;
    if(ishave == false) //若不含有大写字母
    {
     
        for(int i = 1;str[i] != '\0';i++)
            if(str[i] >= 'A' && str[i] <='Z')
                return false;
    }
    else
    {
     
        if(str[i+1] >= 'A' && str[i+1] <='Z')   //若第二个字符仍为大写
            for(int i = 1;str[i] != '\0';i++)   //从第二个遍历到最后 若出现非大写则返回false
            {
     
                if(!(str[i] >= 'A' && str[i] <='Z'))
                    return false;
            } 
        else                                    //若第二个字符为小写
            for(int i = 1;str[i] != '\0';i++)   //从第二个遍历到最后 若出现大写返回false
            {
                                        
                if(str[i] >= 'A' && str[i] <='Z')
                    return false;
            } 
    }
    return true;
}


思路二
bool detectCapitalUse(char * str){
     
    int up = 0;
    for(int i = 0; str[i] != '\0';i++)
    {
     
        if(str[i] >= 'A' && str[i] <='Z')
        {
     
            up++;
            if(up <= i)
                return false;
        } 

    }
    if(up == strlen(str) || up <= 1)
        return true;
    else
        return false;
}

125. 验证回文串
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第2张图片

算法思想:
1.设置双指针i,j分别指向字符串头和字符串尾
2.当表头与表尾指针i,j未相遇时,指针i向右遍历,直到遇到第一个字母或数字字符,指针j向左遍历,直至遇到第一个字母或数字字符
3.判断遍历到元素是否相等,若相等则指针继续相向前进

char Tolower (char a)   //将字符转为小写,若本身已经是小写或是数字则直接返回
{
     
    if(a >= 'A' && a <= 'Z')
        return a+32;
    return a;
}
bool isNumOrChar (char a)   //判断是否为字符或者数字
{
     
    if(a >= '0' && a <= '9')
        return true;
    else if(a >= 'a' && a <= 'z')
        return true;
    else if(a >= 'A' && a <= 'Z')
        return true;
    return false;
}
bool isPalindrome(char * s){
     
    int len = strlen(s);
    if(len <= 1)
        return true;
    int i = 0, j = len - 1;
    while(i < j)
    {
     
        while(i < j && !(isNumOrChar(s[i])))    i++;    //指针i向右遍历,直到遇到第一个字母或数字字符
        while(i < j && !(isNumOrChar(s[j])))    j--;    //指针j向左遍历,直至遇到第一个字母或数字字符
            if(i < j && Tolower(s[i]) != Tolower(s[j])) 
                return false;
        i++;
        j--;
    }
    return true;
}

14. 最长公共前缀
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第3张图片

算法思想:
方法一:横向比较
1.初始化最长公共前缀为第一列,公共前缀的长度大小为num
2.从第二个字符串到最后一个字符串开始比较 将每个字符串的元素与第一个字符串进行比较 直到找到第一个不同的元素,此时下标更新为更小的
3.将第一个字符串中下标为num的字符置为’\0’,返回第一个字符串
方法二:纵向比较
1.比较每一列元素是否与第一列元素相同
2.直到找到第一个字符串元素不同的列,将其边界设为下标i,直接返回第一个字符串

本题采用方法二
char * longestCommonPrefix(char ** strs, int strsSize){
     
    if(strsSize == 0)
        return "";
    if(strsSize == 1)
        return strs[0];
    for(int i = 0; i < strlen(strs[0]); i++)                     //遍历每列
    {
     
        for(int j = 1; j < strsSize; j++)                    //遍历每个字符串
            if(strs[j][i] != strs[0][i])
            {
     
                strs[0][i] = '\0';                                            //直接退出循环并设置边界为i
                return strs[0];
            }    
    }
    return strs[0];
}

434. 字符串中的单词数
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第4张图片

算法思想:
1.遍历字符串,若前一个元素是空格当前元素不是空格,则单词个数加一
2.需要对第一个元素做特殊判断,若第一个元素不是空格,则单词个数加一

int countSegments(char * str){
     
    int i = 0, count = 0;
    while(str[i] != '\0')
    {
     
        if((i == 0 || str[i-1] == ' ') && str[i] != ' ')    
            count++;
        i++;
    }
    return count;
}

58. 最后一个单词的长度
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第5张图片

算法思想:
1.初始化计数器count统计字符个数,从结尾开始遍历,遇到非空格元素时个数加一
2.若count == 0且当前元素为空格则继续前进(需要滤掉后面的空格)
若count != 0时且当前元素为空格则直接返回count
3.遍历结束返回count 则说明字符串长度就是字符个数

int lengthOfLastWord(char * str){
     
    int len = strlen(str), count = 0;
    for(int i = len - 1; i >= 0; i--)
    {
     
        if(str[i] != ' ')   //若遇到非空格元素 则更新count的个数
            count++;
        else if(str[i] == ' ' && count == 0)    //滤掉后面的空格
            continue;
        else
            return count;
    }
    return count;
}

字符串的反转

344. 反转字符串
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第6张图片

算法思想:经典双指针思想,交换即可
void reverseString(char* str, int sSize){
     
    if(sSize <= 1)
        return;
    for(int i = 0; i < sSize / 2; i++)
    {
     
        char temp = str[i];
        str[i] = str[sSize - 1 - i];
        str[sSize - 1 - i] = temp;
    }
}
方法二实际上是方法一的更加好写的版本
void reverseString(char* str, int sSize){
     
    int left = 0, right = sSize - 1;
    while(left < right)
    {
     
        char temp = str[left];
        str[left] = str[right];
        str[right] = temp;
        left++;
        right--;
    }
}

541. 反转字符串 II
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第7张图片

算法思想:
1.先求出字符串的长度,然后从第一个字符开始,每隔2k个字符进行遍历
2.双指针法反转长度为k的字符串,left设置为当前下标i,判断i+k-1是否越界,若越界,right置为字符串长度,若未越界则right=i+k-1
3.每隔2k个长度的字符串,将前k个交换

char * reverseStr(char * str, int k){
     
    int len = strlen(str);
    int left, right;
    for(int i = 0; i < len; i += 2 * k)
    {
     
        left = i;
        if(i + k - 1 <= len - 1)    // 从位置i到i+k-1共计k个元素 若未越界 则令右指针为该下标
            right = i + k - 1;
        else
            right = len - 1;        //若已经越界 则令右指针为最后一个下标
        while(left < right)
        {
     
            char temp = str[left];
            str[left] = str[right];
            str[right] = temp;
            left++;
            right--;
        }
    }
    return str;
}

557. 反转字符串中的单词 III
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第8张图片

算法思想:结合字符串与单词的思想
1.遍历字符串,当遇到字符时,前一个不是字符或为第一个元素时,将left置为当前下标,
同时向后遍历,直到遇到空格或字符串结尾,
设置right为遍历结束前一个元素,若未遍历到结尾,则将下标加一
2.对遍历到的单词进行双指针法反转

char * reverseWords(char * str){
     
    int i = 0, left, right;
    while(str[i] != '\0')
    {
     
        if((i == 0 || str[i - 1] == ' ') && str[i] != ' ')
        {
     
            left = i;   //将左指针指向单词的第一个字母
            while(str[i] != ' ' && str[i] != '\0')//找到第一个空格
                i++;
            right = i -1;
            if(str[i] != '\0')
               i++;
            while(left < right) //反转字符串
            {
     
                char temp = str[left];
                str[left] = str[right];
                str[right] = temp;
                left++; right--;
            }
        }
    }
    return str;
}

151. 翻转字符串里的单词
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第9张图片

算法思想:
1.双指针思想的快慢指针思想,设置快指针i指向字符串尾部,从字符串尾部开始向前遍历寻找第一个非空格字符
2.当找到第一个非空格字符后,将慢指针j设置为该字符下标,然后让快指针i继续向前走,寻找第一个空格字符
3.将快指针i+1到慢指针j的元素复制到结果字符串中
4.结尾还需要对新创建的字符串增加’\0’结尾标志(去除最后一个无效的空格)

char * reverseWords(char * str){
     
    int len = strlen(str);
    int i = len - 1, j, count = 0;
    char *result = (char*)malloc(sizeof(char) * (len+1));
    while(i >= 0)
    {
     
        while(i >= 0 && str[i] == ' ' )  i--;    //从后向前寻找第一个非空格
        if(i >= 0)                              //若未遍历到第一个元素 则将j置为i
            j = i;                              //慢指针j设置为该字符下标
        else                                    //若遍历完就已经结束
            break;
        while(i >= 0 && str[i] != ' ') i--; //寻找第一个空格
        for(int k = i + 1; k <= j; k++)
                result[count++] = str[k];
        result[count++] = ' ';                  //count                   
    }
    if(count == 0)
        result[0] = '\0';       //若无字母 直接第一个元素即为空
    else
        result[count-1] = '\0'; //去除最后一个无效的空格
    return result;
}

299. 猜数字游戏
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第10张图片

算法思想:1.利用哈希表B,C统计未出现在对应位置的元素,bulls统计正确元素个数
2.遍历字符串,若secret[i]==guess[i],则将bull加一,否则让B[i]++,C[i]++
3.扫描哈希表,统计重叠元素个数,即为cow的个数

int min (int a, int b)
{
     
    if(a > b)
        return b;
    return a;
}
char * getHint(char * secret, char * guess){
     
    int bull = 0, cow = 0;
    int B[10] = {
     0}, C[10] = {
     0};
    for(int i = 0; secret[i] != '\0'; i++)
    {
     
        if(secret[i] == guess[i])       //secret[i]==guess[i],则将bull加一,否则让B[i]++,C[i]++
            bull++;
        else
        {
     
            B[secret[i] - '0']++;
            C[guess[i] - '0']++;
        }
    }
    for(int i = 0; i < 10; i++)
    {
     
        cow += min(B[i],C[i]);
    }
    char *str = (char*)malloc(sizeof(char) * 10);
    sprintf(str, "%dA%dB", bull, cow);
    return str;
}

696. 计数二进制子串
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第11张图片

算法思想:1.遍历字符串 统计出连续的数字个数 保存在数组count中
2.遍历count 连续子字符串的数量为 sum += min(count[i], count[i+1])

int min(int a, int b)
{
     
    if(a < b)
        return a;
    return b;
}
int countBinarySubstrings(char * s){
     
    int len = strlen(s);
    if(len <= 1)
        return 0;
    int* count = (int*)malloc(sizeof(int) * 50001);
    int pre = s[0], num = 0, k = 0;
    int sum = 0;
    for(int i = 0; i < len; i++)
    {
     
        if(pre == s[i]) //若与之前相同
            num++;
        else            //若不同则更新
        {
     
            count[k++] = num;
            num = 1;
            pre = s[i];
        }    
    }
    count[k] = num; 
    for(int i = 0; i < k; i++)
        sum += min(count[i], count[i+1]);
    return sum;
}

67. 二进制求和
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第12张图片

算法思想:
1.比较两个字符串的大小,取较长的字符串长度+2为返回字符串的长度,因为可能需要进位1,且还需要将最后一位设置为\0
2.从最后一个元素开始向前遍历,直至两个字符串均遍历到结尾结束,将字符串a的数字与字符串数字b上的数字相加,若其中一个字符串遍历到0则将该 位置加0,将结果取余为该位数字,add为二者的进位
3.若需要进位,则直接将第一位设置为1,若无需进位,则将所有元素向前移动一个单位

char * addBinary(char * a, char * b){
     
    int lena = strlen(a), lenb = strlen(b);
    int maxlen = lena > lenb ? lena+2 : lenb+2;
    char* result = (char*)malloc(sizeof(char) * (maxlen));
    result[maxlen - 1] = '\0';
    int add = 0; //用于表示进位
    for(int i = lena - 1, j = lenb - 1, k = maxlen - 2; i >= 0 || j >= 0; i--, j--, k--)
    {
     
        int sum = add;
        if(i >= 0)
            sum += a[i] - '0';
        if(j >= 0)
            sum += b[j] - '0';
        result[k] = sum % 2 + '0';  //更新result数组的值
        add = sum / 2;
    }
    if(add == 1)
        result[0] = '1';    //若需要进位,则直接将第一位设置为1
    else                    //若无需进位,则将所有元素向前移动一个单位
    {
     
        for(int i = 0; i < maxlen - 1; i++)
            result[i] = result[i + 1];  
        result[maxlen - 1] = '\0';
    }
    return result;
}

同类型题415. 字符串相加

43. 字符串相乘

算法思想:1.初始化长为lena+lenb+1的int型数组result用于保存结果,让一个字符串的每一位与另一个字符串的另一位相乘,执行结果为 result[i+j] += (nums1[i]-‘0’) * (nums2[j] - ‘0’)
2.对result数组进行进位,用add保存向下一位的进位数
3.若进位结束后,add不为零,则需要将每个数字向后移动一位
4.将result的结果赋值给返回字符串res
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第13张图片

char * multiply(char * num1, char * num2){
     
    int lena = strlen(num1), lenb = strlen(num2);
    if(num1[0] == '0' || num2[0] == '0')	//若第一项为0,直接返回0
    {
     
        num1[0] = '0';
        num1[1] = '\0';
        return num1;
    }
    int maxlen = lena + lenb + 1;
    int* result = (int*)malloc(sizeof(int) * maxlen);
    char* res = (char*)malloc(sizeof(char) * maxlen);
    for(int i = 0; i <= maxlen-1; i++) //两位数相乘 不进位情况下最高的一位为lena+lenb-2
    {
     
        result[i] = 0;
    }
    for(int i = lena - 1; i >= 0; i--)
        for(int j = lenb - 1; j >= 0; j--)
        {
     
            result[i + j] += (num1[i] - '0') * (num2[j] - '0');
        }
    int add = 0;
    for(int i = lena + lenb - 2; i >= 0; i--)
    {
     
        result[i] += add;
        add = result[i] / 10;
        result[i] = result[i] % 10;
    }
    if(add == 0)//判断最后一项是否需要进位
    {
     
        res[maxlen - 2] = '\0';
        for(int i = 0; i < maxlen - 2; i++)
            res[i] = result[i] + '0';
    }
    else
    {
     
        for(int i = maxlen - 2; i > 0; i--)
        {
     
            result[i] = result[i - 1];
        }
        res[maxlen - 1] = '\0';
        for(int i = 1; i <= maxlen - 2; i++)
            res[i] = result[i] + '0';
        res[0] = add + '0';
    }
    return res;
}

28. 实现 strStr()
《考研向》leetcode数据结构与程序设计刷题(字符串篇,含思路解答)_第14张图片

算法思想:朴素模式匹配算法
1.从目标串字符开始出发,与比对字符串逐个字符比较
2.每次执行设置j=0,表示每次比对字符串走的步数,当j等于比对串的长度时,说明匹配成功,否则目标串向后移动一个单位

int strStr(char * haystack, char * needle){
     
    int lena = strlen(haystack), lenb = strlen(needle);
    if(lena == 0 && lenb != 0)
        return -1;
    else if(lenb == 0)
        return 0;
    int i = 0;
    while(i <= lena - lenb)	//若长度不足,则不再遍历
    {
     
        int j = 0;
        while(haystack[i] == needle[j] && j < lenb) //从目标串字符开始出发,与比对字符串逐个字符比较
        {
     
            i++;
            j++;
        }
        if(j == lenb)
           return i - j;
       i = i - j + 1;
    }
    return -1;
}

你可能感兴趣的:(数据结构,算法,leetcode,字符串)