網(wǎng)站左側(cè)浮動代碼備案查詢站長工具
目錄
前言
1、題1 僅僅反轉(zhuǎn)字母:
解法一:遍歷+swap
參考代碼1:
參考代碼2:
2、題2 . 字符串中的第一個唯一字符:
解法一:暴力解法
解法二:計數(shù)排序(哈希)
參考代碼:
3、題3 字符串相加:?
參考代碼:
4、題4 字符串最后一個單詞的長度:
參考代碼:
總結(jié)
前言
路漫漫其修遠兮,吾將上下而求索;
大家可以自己先嘗試做一下喔~
917. 僅僅反轉(zhuǎn)字母 - 力扣(LeetCode)
387. 字符串中的第一個唯一字符 - 力扣(LeetCode)
415. 字符串相加 - 力扣(LeetCode)
字符串最后一個單詞的長度_??皖}霸_??途W(wǎng)
1、題1 僅僅反轉(zhuǎn)字母:
917. 僅僅反轉(zhuǎn)字母 - 力扣(LeetCode)
用string 中的接口來實現(xiàn)的話,基本上就是遍歷 + 修改;
解法一:遍歷+swap
標(biāo)準(zhǔn)庫中實現(xiàn)了”交換“這一函數(shù)模板;
設(shè)置兩個指針,讓這兩個指針分別找到兩端的英文字母,然后進行交換;整體的邏輯有點像hoare 版本的快速排序;
參考代碼1:
//判斷當(dāng)前字符是否為英文字符bool isLetter(char ch){if((ch >= 'a' && ch <= 'z' )|| (ch >='A' && ch <= 'Z')) return true;else return false;}string reverseOnlyLetters(string s) {//遍歷 + swapint left = 0, right = s.size();while(left < right){//讓left 從左往右找到英文字母while(left<right && !isLetter(s[left])){left++;}//讓right 從右往左找英文字母while(left < right && !isLetter(s[right])){right--;}//如果都找到了并且沒有越界就進行交換if(left<right){swap(s[left++] ,s[right--]);}}return s;}
判斷一個字符是不是英文字母,還有一個現(xiàn)成的接口函數(shù):isalpha?
參考代碼2:
string reverseOnlyLetters(string s) {//遍歷 + swapint left = 0, right = s.size();while(left < right){//讓left 從左往右找到英文字母while(left<right && !isalpha(s[left])){left++;}//讓right 從右往左找英文字母while(left < right && !isalpha(s[right])){right--;}//如果都找到了并且沒有越界就進行交換if(left<right){swap(s[left++] ,s[right--]);}}return s;}
2、題2 . 字符串中的第一個唯一字符:
387. 字符串中的第一個唯一字符 - 力扣(LeetCode)
解法一:暴力解法
將每一個字符均與其他字符按順序比較一遍,如果沒有相等的便是第一個不重復(fù)的字符;
解法二:計數(shù)排序(哈希)
倘若有一堆數(shù),而這些數(shù)的范圍比較集中,那么此時就可以統(tǒng)計這些數(shù)據(jù)出現(xiàn)的次數(shù),然后再去排序;在本題之中,可以利用”統(tǒng)計次數(shù)“的思想,由于本題中只包含小寫字母,于是可以開辟一個大小為26 的數(shù)組來統(tǒng)計整個字符串中字符出現(xiàn)的次數(shù),然后再一次按照字符串s 中字符的順序遍歷并查找計數(shù)數(shù)組中該字符出現(xiàn)的次數(shù),如果為1直接返回就行,沒有找到就返回 -1;本質(zhì)上就是哈希的思想;
參考代碼:
int firstUniqChar(string s) {int count[26] = {0};for(auto ch : s) count[ch-'a']++;//統(tǒng)計、映射for(size_t i = 0;i<s.size();++i){if(count[s[i]-'a'] == 1) return i; }return -1;//沒有找到}
3、題3 字符串相加:?
415. 字符串相加 - 力扣(LeetCode)
本題是典型的大數(shù)相加;
當(dāng)數(shù)據(jù)過大的時候,普通整形沒有辦法進行準(zhǔn)確的表示;而CPU有直接的運算能力也只能為 0~8byte 范圍內(nèi)的;對于大數(shù),可以用字符串來存檔;
在C語言中有兩個接口函數(shù):atoi(將字符串轉(zhuǎn)換成整型), itoa(將整型轉(zhuǎn)換成字符串);
在C++之中也有兩個相似功能的函數(shù):stoi 、to_string;
- stoi: 給string 對象便可以將其轉(zhuǎn)換成對應(yīng)的整型
- to_string : 將整型家族中的數(shù)據(jù)轉(zhuǎn)換成對應(yīng)的字符串
用以上的接口函數(shù)來實現(xiàn)是行不通的,用字符串來存儲一個數(shù)據(jù)可以很長,超出整形家族中可存儲的數(shù)據(jù)范圍,而存在溢出的風(fēng)險;
正確思想:利用字符串來實現(xiàn)加法的運算思想,并實現(xiàn)進位;
首先第一步是取兩個字符串的最后一個字符(不能直接相加,因為字符進行運算?'+' 以ASCII碼值的形式去計算);然后是將獲取到的字符轉(zhuǎn)換成整型,然后再計算;最后是處理進位,需要利用一個變量來記錄進位的信息,下一次相加的時候再加上即可;
還需要注意的是,當(dāng)較短的字符串計算完了之后,不能直接將較長字符串剩余的字符拷貝下來,因為還有可能存在多次進位的情況;eg. 999999999 + 10;
而每次得到的每一位數(shù)字,需要在目標(biāo)字符串中進行頭插或者尾插+旋轉(zhuǎn)字符串;其中頭插的效率十分低下,因為每頭插一個數(shù)據(jù)僅需要挪動數(shù)據(jù);所以此處采用尾插+旋轉(zhuǎn)字符串;
參考代碼:
string addStrings(string num1, string num2) {//獲取兩個字符串最后一個字符string str;int end1 = num1.size()-1, end2 = num2.size()-1;//進位int next = 0;while(end1 >=0 || end2>=0){int x1 = end1 >= 0 ? num1[end1--] -'0' : 0;int x2 = end2 >= 0 ? num2[end2--] - '0' : 0;int ret = x1 + x2 + next;next = ret / 10;//獲取進位的信息ret = ret % 10;//獲取余數(shù)//尾插str += ('0' + ret);}//有可能會連續(xù)進位if(next == 1) str += '1';//旋轉(zhuǎn)reverse(str.begin() , str.end());return str;}
4、題4 字符串最后一個單詞的長度:
字符串最后一個單詞的長度_??皖}霸_??途W(wǎng)
既然是拿到最后一個單詞,那么只要我們從后往后找到第一個空格就行了;
參考代碼:
#include <iostream>
using namespace std;int main()
{//輸入string s;getline(cin,s);//從后往前進行查找size_t pos = s.rfind(' ');cout<<s.size() - pos -1 <<endl;return 0;
}
需要注意的是,此處進行輸入的時候不能使用cin 以及 scanf;
在控制臺、終端輸入的數(shù)據(jù)是輸入在緩沖區(qū)之中;流提取cin、scanf 均是去緩沖區(qū)中拿數(shù)據(jù);而cin、scanf 只要遇到空格或者換行符就會停止讀取數(shù)據(jù),即 cin、scanf 只會拿到空格、換行符之前的數(shù)據(jù);
Q: 為什么cin 和 scanf 遇到空格或者換行符就停止讀取?
- 因為在日常中我們會輸入多個字符串、整型等;而當(dāng)我們輸入多個值的時候,就利用空格進行分割的;C/C++ 規(guī)定,用scanf 和 cin 的時候,不論讀取的數(shù)據(jù)是什么類型,多個值之間默認用空格或者換行進行分割;
故而空格或者換行符會默認為是流提取cin 以及scanf 的分隔符,此時便會導(dǎo)致在讀取帶有空格的字符串,拿不到空格以后的字符;本題中需要利用string 的非成員函數(shù) getline 來解決;
getline 即獲取一行,遇見空格并不會結(jié)束讀取,默認遇見換行符才會停止讀取;除此之外,我們還可以指定getline 的終止符;
總結(jié)
熟悉使用 string 的接口函數(shù)~