力扣剑指offer刷题博客第一篇,后续会更完所有题目,题库链接https://leetcode-cn.com/problemset/lcof/
每道题力求多种解法!!!
目录
左旋转字符串
1.暴力做法
class Solution {
public:
string reverseLeftWords(string s, int n) {
int len=s.length();
string ans="";
for(int i=n;i<len;++i){
ans+=s[i];
}
for(int i=0;i<n;++i){
ans+=s[i];
}
return ans;
}
};
执行用时:8 ms, 内存消耗:7.5 MB
2.STL版
class Solution {
public:
string reverseLeftWords(string s, int n) {
int len=s.length();
string ans=s.substr(n,len-n);//substr(a,b):a表示起始位置,b表示从起始位置开始算的字符数
for(int i=0;i<n;++i){
ans+=s[i];
}
return ans;
}
};
注:substr(a,b):a表示起始位置,b表示从起始位置开始算的字符数 ,即获取从位置a开始长度为b的字符串(字符串初始位置为0)
执行用时:4 ms, 在所有 C++ 提交中击败了84.52%的用户
内存消耗:7.5 MB, 在所有 C++ 提交中击败了64.48%的用户
3.三次反转字符串的骚操作(题解区学来的)
思路:
(1)重写reverse函数,因为我们要实现特定位置的反转,原来的函数不足以支持这项操作,原本是reverse(s.begin(),s,end()),s.begin()表示的是取s的首元素地址
(2)将原字符串s分为两个子串,要转移到尾部的是s1,另一个为s2,设s="abcde",k=2,结果为s="cdeab"
s1=ab,s2=cde
i.先将s2整体反转,s2=edc
ii.反转s,s=cdeba,此时s1(别忘了这表示要移到尾部的字符串)已经在尾部了,但是顺序不对,所以要再反转s1
iii.反转s1得到最终结果s=cdeab
class Solution {
public:
string reverse(string &s,int i,int j){
while(i<j){
char temp=s[i];
s[i++]=s[j];
s[j--]=temp;
}
return s;
}
string reverseLeftWords(string s, int n) {
int len=s.length();
reverse(s,n,len-1);
reverse(s,0,len-1);
reverse(s,len-n,len-1);
return s;
}
};
剑指 Offer 55 - I. 二叉树的深度
1.后序遍历二叉树(DFS--深度优先搜索)
后序遍历:左(左子树)右(子树)中(父节点)
注:最后return+1表示浏览当前节点即父(相对于左右子树来说的)节点
深度优先搜索:一条路走到黑,前面没有路了再往后退到离得最近的分岔口走另一条还没走过的路,常用递归或栈实现
找出左右子树的深度,最后取两者之中的最大值+1就是结果
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root== NULL)return NULL;//空指针要返回 不然会报错
int t1=maxDepth(root->left);
int t2=maxDepth(root->right);
return max(t1,t2)+1;
}
};
执行用时:4 ms, 在所有 C++ 提交中击败了98.98%的用户
内存消耗:18.4 MB, 在所有 C++ 提交中击败了85.66%的用户
之前做错的代码和错误样例,错误原因是重复计算了深度,低级错误!!!
2.层次遍历(BFS--广度优先搜索)
层次遍历:遍历过程如其名字,先遍历完上一层所有元素再遍历下一层元素,队列结合while实现
思路:
val作用是用来标记当前层数,每次弹出队首元素时与结果变量对比一次取最大值;
每次浏览当前节点
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==NULL)return 0;//空树直接返回0
queue<TreeNode*>q;
root->val=1;
q.push(root);//入队
int ans=0;
while(!q.empty()){
TreeNode* temp=q.front();//取队首元素
ans=max(temp->val,ans);
q.pop();//出队
if(temp->left){
temp->left->val=temp->val+1;
q.push(temp->left);
}
if(temp->right){
temp->right->val=temp->val+1;
q.push(temp->right);
}
}
return ans;
}
};
执行用时:8 ms, 在所有 C++ 提交中击败了92.63%的用户
内存消耗:18.6 MB, 在所有 C++ 提交中击败了79.93%的用户
3.层次遍历的另一个版本
双重while,虽然用时和内存不太行,思路还是值得借鉴
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==NULL)return 0;
queue<TreeNode*>q;
q.push(root);//入队
int ans=0;
while(!q.empty()){
queue<TreeNode*>p;
while(!q.empty()){ //刚开始进入第二重while时,q内遗留的是当前层的所有节点
TreeNode* temp=q.front();//取队首元素
if(temp->left){
p.push(temp->left);
}
if(temp->right){
p.push(temp->right);
}
q.pop();
}
//退出第二重while循环后p内存的是下一层所有节点
ans++;
q=p;//当前层遍历完毕进入下一层
}
return ans;
}
};
执行用时:16 ms, 在所有 C++ 提交中击败了46.09%的用户
内存消耗:20.4 MB, 在所有 C++ 提交中击败了5.17%的用户