目录
1.剑指Offer
面试题58:左旋转字符串
题目描述:
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
思路:将字符串按循环的位数分为两部分,分别对每部分进行翻转,再对整个字符串进行翻转。
代码:
class Solution {
public:
string LeftRotateString(string str, int n) {
if(!str.empty()){ //注意nullptr
int len=str.size();
if(len>0&&n>0&&n<len){ //注意内存越界
Reverse(str,0,n-1);
Reverse(str,n,len-1); //注意内存越界
Reverse(str,0,len-1);
}
}
return str;
}
void Reverse(string &str, int i, int j){
while(i<j){
char a=str[i];
str[i]=str[j];
str[j]=a;
i++;
j--;
}
}
};
力扣:反转字符串II
题目描述:
给定一个字符串和一个整数 k,你需要对从字符串开头算起的每个 2k 个字符的前k个字符进行反转。如果剩余少于 k 个字符,则将剩余的所有全部反转。如果有小于 2k 但大于或等于 k 个字符,则反转前 k 个字符,并将剩余的字符保持原样。
示例:
要求:
- 该字符串只包含小写的英文字母。
- 给定字符串的长度和 k 在[1, 10000]范围内。
代码:
class Solution {
public:
string reverseStr(string s, int k) {
if(!s.empty()){
int len=s.size();
for(int i=0;i<len;i+=2*k){
int j=(i+k>len?len:i+k);
Reverse(s,i,j-1);
}
}
return s;
}
void Reverse(string &s, int i, int j){
while(i<j){
swap(s[i++],s[j--]);
}
}
};
面试题62:圆圈中最后剩下的数字
题目描述:每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
思路:环形链表或数学规律求解
代码:
方法1:数学规律
递归关系:
n=1, f(n,m)=0;
n>1,f(n,m)=(f(n-1,m)+m)%n;
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<1||m<1) return -1;
int last=0;
for(int i=2;i<=n;i++){
last=(last+m)%i;
}
return last;
}
};
方法2:环形链表
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<1||m<1){
return -1;
}
list<int> numbers;
for(int i=0;i<n;i++){
numbers.push_back(i);
}
list<int>::iterator current=numbers.begin();
while(numbers.size()>1){
for(int i=1;i<m;i++){ //走m-1步
++current;
if(current==numbers.end()){
current=numbers.begin();
}
}
list<int>::iterator next=++current;
if(next==numbers.end()){
next=numbers.begin();
}
--current;
numbers.erase(current);
current=next;
}
return *current;
}
};
2.Leetcode
例1:从下往上的层次遍历
题目描述:
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root).
For example:
Given binary tree{3,9,20,#,#,15,7},
3
/ \
9 20
/ \
15 7
return its bottom-up level order traversal as:
[
[15,7]
[9,20],
[3],
]
confused what"{1,#,2,3}"means? > read more on how binary tree is serialized on OJ.
OJ's Binary Tree Serialization:
The serialization of a binary tree follows a level order traversal, where '#' signifies a path terminator where no node exists below.
Here's an example:
1
/ \
2 3
/
4
\
5
The above binary tree is serialized as"{1,2,3,#,#,4,#,#,5}".
思路:层序遍历加反转
代码:
class Solution {
public:
vector<vector<int> > levelOrderBottom(TreeNode *root) {
vector<vector<int> > res;
if(root==nullptr){
return res;
}
queue<TreeNode *> q;
q.push(root);
while(!q.empty()){
int count=q.size();
vector<int> temp;
while(count--){
TreeNode *p=q.front();
q.pop();
temp.push_back(p->val);
if(p->left){
q.push(p->left);
}
if(p->right){
q.push(p->right);
}
}
res.push_back(temp);
}
reverse(res.begin(),res.end());
return res;
}
};
例2:通过中序和后序遍历重建二叉树
题目描述:
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
思路:深度遍历、递归实现。
代码:
class Solution {
public:
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
int inlen=inorder.size();
int postlen=postorder.size();
return dfs(inorder,0,inlen-1,postorder,0,postlen-1);
}
TreeNode *dfs(vector<int> &inorder, int inStart, int inEnd, vector<int> &postorder, int postStart, int postEnd){
if(inStart>inEnd){
return nullptr;
}
TreeNode *root=new TreeNode(postorder[postEnd]);
int middle;
for(middle=inStart;middle<=inEnd;middle++){
if(inorder[middle]==root->val){
break;
}
}
int leftlen=middle-inStart;
root->left=dfs(inorder,inStart,middle-1,postorder,postStart,postStart+leftlen-1);
root->right=dfs(inorder,middle+1,inEnd,postorder,postStart+leftlen,postEnd-1);
return root;
}
};
错误解法:缺少停止条件
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
int postlen=postorder.size();
int inlen=inorder.size();
if(postorder.empty()||inorder.empty()){
return nullptr;
}
int rootval=postorder[postlen-1];
vector<int> leftInorder;
vector<int> rightInorder;
vector<int> leftPostorder;
vector<int> rightPostorder;
int i=0;
for(;i<inlen&&inorder[i]<rootval;i++){
leftInorder.push_back(inorder[i]);
}
for(int j=i;j<inlen&&inorder[i]>rootval;j++){
rightInorder.push_back(inorder[j]);
}
int k=0;
for(;k<postlen&&postorder[k]<rootval;k++){
leftPostorder.push_back(postorder[k]);
}
for(int l=k;l<postlen&&postorder[l]>rootval;l++){
rightPostorder.push_back(postorder[l]);
}
TreeNode *root=new TreeNode(rootval);
root->left=buildTree(leftInorder,leftPostorder);
root->right=buildTree(rightInorder,rightPostorder);
return root;
}
};