1.二维数组中的查找
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
vector<int>:: iterator j;
vector<vector<int>>:: iterator i;
for(i=array.begin();i!=array.end();i++){
for(j=(*i).begin();j!=(*i).end();j++){
if((*j)==target){
return 1;
}
}
}
return 0;
}
};
使用迭代器遍历,时间复杂度o(n*m),因为数据是递增的也可以用二分法查找,复杂度可优化至o(n*logm)。
2.替换空格
请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
class Solution {
public:
void replaceSpace(char *str,int length) {
int after_length=length;
for(int i=0;i<length;i++){
if(str[i]==' '){
after_length+=2;
}
}
str[after_length]='\0';
for(int i=after_length-1,j=length-1;i>=0;i--,j--){
if(str[j]==' '){
str[i--]='0';
str[i--]='2';
str[i]='%';
}else{
str[i]=str[j];
}
}
}
};
先计算出替换后要占的空间,再从尾到头替换,保证已处理的数据不影响未处理的数据
3.从尾到头打印链表
输入一个链表,从尾到头打印链表每个节点的值。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> ans;
vector<int> _stack;
int i=0;
while(head!=NULL){
_stack.push_back(head->val);
i++;
head=head->next;
}
i-=1;
while(i>=0){
ans.push_back(_stack[i]);
i--;
}
return ans;
}
};
输入到栈中再输出
4.重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if(vin.size()==0){
return NULL;
}
int mid=pre[0];
TreeNode *node=new TreeNode(mid);
vector<int> left_pre,right_pre,left_vin,right_vin;
int i=0;
while(vin[i]!=mid){
left_pre.push_back(pre[i+1]);
left_vin.push_back(vin[i]);
i++;
}
i++;
while(i<vin.size()){
right_pre.push_back(pre[i]);
right_vin.push_back(vin[i]);
i++;
}
node->left=reConstructBinaryTree(left_pre,left_vin);
node->right=reConstructBinaryTree(right_pre,right_vin);
return node;
}
};
前序遍历的第一个数就是根节点,将中序遍历分为左右子树后递归构造
5.用两个栈实现队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.top());
stack1.pop();
}
}
int ans=stack2.top();
stack2.pop();
return ans;
}
private:
stack<int> stack1;
stack<int> stack2;
};
入队的元素进入栈1中,栈1的元素再出栈进入栈2,则栈2的元素按照队列顺序排列。出队时栈2的栈顶元素出栈即可。需要注意的是栈2的元素没必要倒入栈1中,需要出队就继续读取栈2中的元素直到为空,因为后来入队的元素不影响队首的已经进入栈2的元素。
6.旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int nsize=rotateArray.size();
if(nsize==0)
return 0;
for(int i=0;i<nsize-1;i++){
if(rotateArray[i]>rotateArray[i+1])
return rotateArray[i+1];
}
return rotateArray[0];
}
};
数组原本是递增的,旋转后最小的数字会在比他大的数字后面,否则就是没有旋转,第一个就是最小数字,遍历一遍即可。也可以用二分法优化,上半部分的数字一定比下半部分的数字大,二分逼近最小数字所在位置,但是有重复数字时只能遍历,比较麻烦。
7.斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
n<=39
class Solution {
public:
int Fibonacci(int n) {
int a=1,b=1,c;
if(n==0)
return 0;
if(n<3)
return 1;
for(int i=3;i<=n;i++){
c=a+b;
a=b;
b=c;
}
return b;
}
};
8.跳台阶
class Solution {
public:
int jumpFloor(int number) {
int a=1,b=1,c;
int n=number;
if(n==0)
return 0;
if(n<2)
return 1;
for(int i=2;i<=n;i++){
c=a+b;
a=b;
b=c;
}
return b;
}
};
实际也是斐波那契数列,当前的级数可以从n-1级和n-2级跳上来,即前面两种状态的和
9.变态跳台阶
class Solution {
public:
int jumpFloorII(int number) {
int ans[100];
ans[1]=1;
ans[2]=2;
for(int i=3;i<=number;i++){
ans[i]=1;
for(int j=1;j<i;j++){
ans[i]+=ans[j];
}
}
return ans[number];
}
};
当前状态是前面所有状态之和,实际上找规律可以发现答案只是2的n-1次方。
10.矩阵覆盖
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
class Solution {
public:
int rectCover(int number) {
int a=1,b=1,c;
int n=number;
if(n==0)
return 0;
if(n<2)
return 1;
for(int i=2;i<=n;i++){
c=a+b;
a=b;
b=c;
}
return b;
}
};
实际上也是斐波那契数列。大矩形的最右端的图形只有两种情况,一个竖条或者两个横条,所以组合方法可以理解成(n-1个+1个竖条)和(n-2个+两个横条)的方案之和。