leetcode 初级算法 字符串(C++)

1.反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]

示例 2:
输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]

思路,遍历从0到n/2,对应位置进行交换

class Solution {
public:
    void reverseString(vector<char>& s) {
        if (s.size()==1)return;
        for(int i =0;i<(s.size()/2);i++)swap(s[i],s[s.size()-i-1]);//相当于做了一次对称变换
    }
};

2.整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:
输入: 123
输出: 321

示例 2:
输入: -123
输出: -321

示例 3
输入: 120
输出: 21

注意:假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

思路:

不断取模运算,生成新的数字。注意C++中取模运算的细节,先做除法,用除法结果乘以除数再用被除数减去
(-7/3) => -2
-2 * 3 => -6
so a%b => -1

同时为了解决int的溢出,计算使用long类型

static const int iMIN = 0X80000000;
static const int iMAX = 0X7FFFFFFF;

class Solution {
    public:
        int reverse(int x) {
            long L = 0;

            while(x != 0) {
                L = L * 10 + x % 10;
                x = x / 10;
            }
            if(L > iMAX || L < iMIN)
                return 0;
            return L;//这手秒啊,遇到int类型的溢出问题可以用long来处理。
        }
    };

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

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

案例:
s = "leetcode"
返回 0.
s = "loveleetcode",
返回 2.

思路:维护一个26大小的int数组,记录每个单词出现的个数,两次遍历,第一次记录各个字母的个数,第二个找出第一个出现次数为1的

class Solution {
public:
    int firstUniqChar(string s) {
        vector<int> record(26,0);
        if(s.length()==0)return -1;
        for (int i = 0; i < s.length(); ++i) {
            record[s[i]-'a']++;//统计字母个数
        }

        for (int k = 0; k < s.length(); ++k) {
            if(record[s[k]-'a']==1)return k;//找到第一个只出现一次的字母
        }
        return -1;
    }
};

4.有效的字母异位词

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

示例 1:
输入: s = "anagram", t = "nagaram"
输出: true

示例 2:
输入: s = "rat", t = "car"
输出: false

思路:和上一题类似,用一个数组维护,遍历数组完成判断。

第一次遍历第一个数组s,统计数字++
第二次遍历第二个数组t,统计数字--
第三次遍历维护的数组,看看是否都为0;

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size()!=t.size())return false;
        vector<int> alpha(26,0);
        for(int i = 0;i<s.length();i++)alpha[s[i]-'a']++;//第一个字符串来说,找到字母对应位置++
        for(int i = 0;i<t.length();i++)alpha[t[i]-'a']--;//第二个字符串来说,找到字母对应位置--
        for(int i = 0;i<alpha.size();i++)if(alpha[i]!=0)return false;//判断是否全为0;
        return true;
    }
};

5.验证回文字符串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:
输入: "A man, a plan, a canal: Panama"
输出: true

示例 2:
输入: "race a car"
输出: false

思路:

1.先对字符串进行处理:只保留数组字母的小写
2.判断是否对称,for循环和倒转字符串类似,遍历从0到n/2

class Solution {
public:
    bool isPalindrome(string s) {
        vector<char> result;
        for(int i = 0;i<s.length();i++){
            if(s[i]>='a'&&s[i]<='z'){//小写字母的情况
                result.push_back(s[i]);
            }else if(s[i]>='A'&&s[i]<='Z'){//大写字母的情况
                result.push_back(s[i]-'A'+'a');
            } else if(s[i]>='0'&&s[i]<='9'){//数字的情况
                result.push_back(s[i]);
            }
        }
        for(int i = 0;i<(result.size()/2);i++){
            if(result[i]!=result[result.size()-1-i])return false;
        }
        return true;
    }
};

6.字符串转换整数 (atoi)

请你来实现一个 atoi 函数,使其能将字符串转换成整数。首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

示例 1:输入: "42"
输出: 42

示例 2:输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。

示例 3:
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。

示例 4:
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。 因此无法执行有效的转换。

示例 5:
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。因此返回 INT_MIN (−231)

思路

就按照给的要求写就行
处理int型溢出同样使用了long类型来确保精度不会丢失。

class Solution {
public:
    int myAtoi(string str) {
        long result = 0;
        long temp = 0;
        bool negative=false;//是否为负数
        if(str.length() == 0)return 0;//特殊情况
        
        int k = 0;
        for(int i = 0;i<str.length();i++){//忽略前面的空格
            if(str[i]!=' ')break;
            k++;
        }
        if(k==str.length())return 0;//全是空格的情况
        
        if(str[k]=='+'){//判断+-
            k++;
        }else if(str[k]=='-'){
            k++;
            negative = true;
        }else if((str[k]>='0'&&str[k]<='9'));
        else return 0;
        
        while (k<str.length()){
            if(str[k]>='0'&&str[k]<='9'){
                result = result*10+str[k]-'0';
            }else break;
            k++;
            if(negative)temp = -result;
            else temp = result;
            if(temp>=INT_MAX)return INT_MAX;
            if(temp<=INT_MIN)return INT_MIN;
        }
        if(negative)result = -result;
        if(result>=INT_MAX)return INT_MAX;
        if(result<=INT_MIN)return INT_MIN;
        return result;
    }
};

7.实现strStr()

实现 strStr() 函数。给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 1:
输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:
输入: haystack = "aaaaa", needle = "bba"
输出: -1

思路

遍历第一个数组,再遍历第二个数组判断,需要两个r循环嵌套。但是需要注意几个细节:
字符串大小,两个字符串长度差值,各层循环次数

class Solution {
public:
    int strStr(string haystack, string needle) {
        if(needle.length()==0)return 0;
        auto count = haystack.length()-needle.length()+1;//计算字符串长度差值,确定外层循环次数
        if(count<1)return -1;
        for(int i = 0;i<count;i++){//外层循环,遍历haystack
            int j = 0;
            while (j<needle.length()){//内层循环,遍历needle,不用for循环。需要利用j最后的值来判断是否相同
                if(haystack[i+j]!=needle[j])break;
                j++;
            }
            if(j==needle.length())return i;
        }
        return -1;
    }
};

8.报数

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

  1. 1
    
  2. 11
    
  3. 21
    
  4. 1211
    
  5. 111221
    

1 被读作 "one 1" ("一个一") , 即 11。
11 被读作 "two 1s"("两个一"), 即 21。
21 被读作 "one 2", "one 1"("一个二" , "一个一") , 即 1211。

给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。注意:整数顺序将表示为一个字符串。

示例 1:
输入: 1
输出: "1"

示例 2:
输入: 4
输出: "1211"

3.思路

有点像DP的题目,因为当前答案需要之前的结果
那么维护一个二维数组来存放之前的结果,进行循环计算就好了。空间没优化(其实不用二维数组,只保留上一次的就可以)

class Solution {
public:
    string countAndSay(int n) {
        vector<vector<int >> results;//存放1-n的式子
        //第一个式子 first 只有一个1
        vector<int> first;
        first.push_back(1);
        results.push_back(first);
        
        for(int i = 1;i < n; i++){//n次循环,构造结果
            vector<int> temp;//要构造的数组
            for(int j = 0;j<results[i-1].size();){
                int count=1;
                int target=results[i-1][j];
                for(int k = j+1;k<results[i-1].size();k++){
                    if(results[i-1][k]!=target)break;
                    else{
                        count++;
                    }
                }
                j=j+count;
                temp.push_back(count);
                temp.push_back(target);
            }
            results.push_back(temp);
        }
        
        vector<int> result = results.back();//取最后一个
        string answer;
        for(int i = 0;i<result.size();i++){
            char c = '0'+result[i];
            answer.append(1,c);
        }
        //cout<<"the answer of "<<n<<"is:"<<answer<<endl;
        return answer;
    }
};

9.最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""。

示例 1:
输入: ["flower","flow","flight"]
输出: "fl"

示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。

思路

还好是找前缀,不是字串问题
挨个遍历就行了,不是很难

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        string result="";
        if(strs.size()<1)return result;
        for(int i = 0;i<strs[0].size();i++){//从下标0开始找
            char c = strs[0][i];
            for(int j = 1;j<strs.size();j++){//遍历每一个数组
                if(i>=strs[j].size()||c!=strs[j][i])return result;//注意判断其他字符串大小,防止越界访问
            }
            result.push_back(c);
        }
        return result;
    }
};
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  •   引用类型的值(对象)是引用类型的一个实例。   在 ECMAscript 中,引用类型是一种数据结构,用于将数...
    霜天晓阅读 1,035评论 0 1
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,204评论 0 4
  • 这是进入简书时界面上的内容。 《海上钢琴师》里有一句话大致是这样说的:只要你有故事,可以找人讲讲,就还不算完。所以...
    Clytie_阅读 283评论 0 0
  • 结束语:就是把两个值放入数组中,{b , b = a} ,第一元素是b的值,第二个是a的值(些时a把值赋值给了b)...
    else05阅读 1,292评论 0 0
  • 老六沉默寡言,他一个月的话可能还没有老四一天的话多。 除了身高不能加分之外,他可以算作标准的帅哥了。姑且不去描述他...
    封狼居胥阅读 1,041评论 8 11