算法练习——字符串

一:最长公共前缀和

题目要求:

解题思路:

法一

遍历strs,两者一一对比,得到最终答案

法二

统一遍历,同时遍历strs中每个字符串

通过两个for循环,

外循环i表示strs中单个字符串从0到结尾,即 0 <= i < strs[0].size();

内循环j表示strs中,字符串的总数,         即 1 <= j < strs.size();

:第一行作为对照行,因此j从1开始。

实现代码:

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        string ret("");
        for(int i = 0; i < strs[0].size(); i++)
        {
            char n = strs[0][i];
            for(int j = 1; j < strs.size(); j++)
            {
                if(strs[j][i] == '\0' || strs[j][i] != n) 
                {
                    return ret;
                }
            }
            ret += n;
        }
        return strs[0];
    }
};

二:最长回文子串

题目要求:

解题思路:

思路:中心扩散法

定义变量i遍历字符串s

先判断奇数情况:定义变量 left = i,right = i; 

若s[left] == s[right]   left--; right++;

再判断偶数情况:令left = i, right = i+1;

同样若s[left] == s[right]   left--; right++;

注1.奇偶顺序不影响最终结果

注2.注意边界条件,left >=0 && right < s.size();

实现代码:

class Solution {
public:
    string longestPalindrome(string s) {
        int begin = 0, len = 0;//因为要记录子串的大小,开始定义两个变量,来记录子串的起始位置和长度
        for(int i = 0; i < s.size(); i++)
        {
            int right = i, left = i;
            while(left >= 0 && right < s.size() && s[right] == s[left])
            {
                right++;
                left--;
            }
            if(right - left - 1 > len) 若当前子串大于len,更新begin和len
            {
                begin = left + 1;
                len = right - left - 1;
            }
            right = i + 1, left = i;
            while(left >= 0 && right < s.size() && s[right] == s[left])
            {
                right++;
                left--;
            }
            if(right - left - 1 > len) 
            {
                begin = left + 1;
                len = right - left - 1;
            }            
        }
        return s.substr(begin,len);
    
    }
};

三:二进制求和

题目要求:

解题思路:

思路:数学上两数相加是从右向左加的,因此遍历字符串a、b也应当从右向左遍历。

定义一个变量t,将变量t与字符串逐位相加 → t += a[i] - '0';  t+= b[i] - '0';

注1.字符数字x转整型数字x → x - '0';

注2.注意边界,t+=各个字符前,保证i >= 0; 

实现代码:

class Solution {
public:
    string addBinary(string a, string b) {
        int cur1 = a.size() - 1, cur2 = b.size() - 1, t = 0;
        string ret("");
        while(cur1 >= 0 || cur2 >=0 || t)//当t不为0时,说明此时进位不为0,还需往前进一位,循环内的if条件保证了a、b字符串不会越界
        {
            if(cur1 >= 0)
            {
                t += a[cur1--] - '0';
            }
            if(cur2 >= 0)
            {
                t += b[cur2--] - '0';
            }
            ret += t % 2 + '0';
            t /= 2;
        }
        reverse(ret.begin(),ret.end());
        return ret;
    }
};

四:字符串相乘

题目要求:

解题思路:

思路(以示例2为例):如果按照往常的思维逻辑,数学乘法应当从中间过程就考虑进位,如图所示:

但是这种方法用代码较为难以实现,考虑的细节很多。

如果我们按以下思路:先将字符串翻转,然后再从左向右不进位相乘,将得到数求和存入到数组中,最后再遍历数组处理进位,这样用代码实现起来就简单了很多,如图所示:

最后按照二进制求和的思路,便能得到最终答案。

实现代码:

class Solution {
public:
    string multiply(string num1, string num2) {
        reverse(num1.begin(),num1.end());
        reverse(num2.begin(),num2.end());
        int len1 = num1.size(), len2 = num2.size();
        vector<int> ret(len1 + len2 ,0);
        for(int i = 0; i < len2; i++)
        {
            for(int j = 0; j < len1; j++)
            {
                ret[i+j] += (num2[i] - '0') * (num1[j] - '0');
            }
        }
        int t = 0;
        string tmp("");
        for(auto n : ret)
        {
            t += n;
            tmp += t % 10 + '0';
            t /= 10;
        }
        while(tmp.size() > 1 && tmp.back() == '0')
        {
            tmp.pop_back();
        }
        reverse(tmp.begin(),tmp.end());
        return tmp;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值