根据leetcode上的顺序:剑指offer
文章目录
字符串
剑指 Offer 05. 替换空格
思路
首先记录这个字符串中的空格的数量count,然后对s进行resize,扩充为oldSize+2*count,然后从后往前进行复写。遇到非空格直接复制,遇到空格就按照顺序复写"%20"。
代码
class Solution {
public:
string replaceSpace(string s) {
int oldSize = s.size();
int count = 0;
for(auto c:s){
if(c == ' ')
count++;
}
s.resize(count*2 + oldSize);
int newSize = s.size();
for(int i = newSize - 1, j = oldSize - 1; i >= 0, j >= 0;i--, j--){
if(s[j] == ' '){
s[i] = '0';
s[i - 1] = '2';
s[i - 2] = '%';
i -= 2;
}
else{
s[i] = s[j];
}
}
return s;
}
};
剑指 Offer 58 - II. 左旋转字符串
思路
左旋转字符串是把字符串前面的n个字符转移到字符串的尾部。这里可以通过一个小技巧来实现。
abcdefg, n=2把字符串分为abcdefg两部分,然后进行三次反转。
- 反转前n个字符,bacdefg
- 反转后面的字符,bagfedc
- 整体反转,cdefgab
至于反转函数,可以直接用std里的string的reverse,比如
reverse(s.begin(), s.begin() + n)
也可以直接重新写一个函数。
代码
class Solution {
public:
string replaceSpace(string s) {
int oldSize = s.size();
int count = 0;
for(auto c:s){
if(c == ' ')
count++;
}
s.resize(count*2 + oldSize);
int newSize = s.size();
for(int i = newSize - 1, j = oldSize - 1; i >= 0, j >= 0;i--, j--){
if(s[j] == ' '){
s[i] = '0';
s[i - 1] = '2';
s[i - 2] = '%';
i -= 2;
}
else{
s[i] = s[j];
}
}
return s;
}
};
剑指 Offer 20. 表示数值的字符串
思路
没什么好说的,模拟,考虑到所有情况
代码
class Solution {
public:
bool isNumber(string s) {
//先去除前后的空格
int front = 0;
for(int i = 0; i < s.size(); i++){
if(s[i] == ' '){
front++;
}
else{
break;
}
}
s.erase(s.begin(),s.begin() + front);
int back = s.size();
for(int i = s.size() - 1; i >= 0; i--){
if(s[i] == ' '){
back--;
}
else{
break;
}
}
s.erase(s.begin() + back,s.end());
//三个flag记录这三个东西是否出现过
bool numFlag = false;
bool dotFlag = false;
bool eFlag = false;
for(int i = 0; i < s.size(); i++){
//如果是'+'或者'-',且符号只能出现在第一位或者e后面
if((s[i] == '+' || s[i] == '-') && (i == 0 || s[i-1] == 'e' || s[i-1] == 'E')){
continue;
}
//如果是数字
else if(isdigit(s[i])){
numFlag = true;
}
//如果是'.',但是需要没出现过'.'和'e'
else if(s[i] == '.' && dotFlag == false && eFlag == false){
dotFlag = true;
}
//如果是'e',需要没出现过'e'且出现过数字,满足条件后要把出现过数字的numFlag调为false
else if((s[i] == 'e' || s[i] == 'E') && eFlag == false && numFlag == true){
eFlag = true;
numFlag = false;
}
else{
return false;
}
}
return numFlag;
}
};
剑指 Offer 67. 把字符串转换成整数
思路
也是一个模拟为主的题目。需要注意的是要用long类型来保存临时的结果,因为可能会溢出,所以先用long来保存。然后用一次(int)来强转ans的结果,如果(int)ans和ans的结果不一样,说明ans对于int类型来说是溢出的。
代码
class Solution {
public:
int strToInt(string str) {
int n = str.size();
long ans = 0;//防止溢出,先把ans设置为long
//记录空格后的第一位
int i = 0;
while(i < n && str[i] == ' '){
i++;
}
if(i == n){
return 0;
}
//记录符号位
int flag = 1;
if(str[i] == '+'){
i++;
}
else if(str[i] == '-'){
flag = -1;
i++;
}
//记录数字
while(i < n && str[i] >= '0' && str[i] <= '9'){
ans = ans*10 + str[i] - '0';
if(ans > INT_MAX){
break;
}
i++;
}
//如果有溢出,转化结果
if(int(ans) != ans){
return flag == 1 ? INT_MAX:INT_MIN;
}
return flag*ans;
}
};
链表
剑指 Offer 06. 从尾到头打印链表
思路
可以用遍历的方法来做,也可以直接翻转链表来实现。这里采用翻转链表的方法,需要定义几个节点,比如pre、cur、temp,然后使用一个辅助函数来实现翻转。
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverse(ListNode* head){
ListNode* pre = nullptr;
ListNode* cur = head;
while(cur){
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
vector<int> reversePrint(ListNode* head) {
vector<int> ans;
head = reverse(head);
while(head){
ans.push_back(head->val);
head = head->next;
}
return ans;
}
};