1.在二维数组中查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
解题思路:
找到左下角 从左下角看 向上是递减 向上是递增
代码时注意数组的越界问题
STL的使用方法 在 verctor使用size()
获取列array[0].size()
获取列
`class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int row=array.size();
int col=array[0].size();
int i=row-1,j=0;
while(i>=0&&j<col){
if(target<array[i][j])
i--;
else if (target>array[i][j])
j++;
else
return true;
}
return false;
}
};`
2.替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
解题思路:
从前向后遍历 从后向前插入
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
w | e | a | r | e | h | a | p | p | y | ||||||
w | e | % | 2 | 0 | a | r | e | % | 2 | 0 | h | a | p | p | y |
插入前后可以看出 空格从2 号位变为 2-4号位 插入时从后插入用i+count*2 可以定位到%20的尾位
class Solution {
public:
void replaceSpace(char *str,int length) {
int count =0;
for(int i=0;i<length;i++)
{
if(str[i]==' ')
count++;
}
for(int i=length-1;i>=0;i--)
{
if(str[i]==' ')
{
str[i+count*2]='0';
str[i+count*2-1]='2';
str[i+count*2-2]='%';
count--;
}
else
{
str[i+count*2]=str[i];
}
}
}
};
3.从头到尾打印链表
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
解题思路:
题目要求打印出一个数组 并不是链表反转
思路:1 利用栈
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
ListNode *p=NULL;
p=head;
vector<int> value;
stack<int > temp;
while(p!=NULL)
{
temp.push(p->val);
p=p->next;
}
while(!temp.empty()){
value.push_back(temp.top());
temp.pop();
}
return value;
}
};
思路:2 使用数组反转
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
ListNode *p=NULL;
p=head;
vector<int> value;
while(p!=NULL)
{
value.push_back(p->val);
p=p->next;
}
int i=0;
int j=value.size()-1;
while(i<j)
{
swap(value[i++],value[j--]);
}
return value;
}
};
4.重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路:
前序遍历第一个数 必是根节点 中序遍历 根节点前的数必为左子树 所以可以确定 左子树的长度
然后通过递归 不断对剩下的子树切分 让他们分为左右子树
注意 数组边界 前序数组左半边包括根节点 所以需要i+1 右半边则和中序数组一致
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int len=vin.size();
if(len==0)
return NULL;
vector<int> pre_left,pre_right,vin_left,vin_right;
TreeNode *head=new TreeNode(pre[0]);
int rp=0;
for(int i=0;i<len;i++)
{
if(vin[i]==pre[0])
{
rp=i;
break;
}
}
for(int i=0;i<rp;i++)
{
pre_left.push_back(pre[i+1]);
vin_left.push_back(vin[i]);
}
for(int i=rp+1;i<len;i++)
{
pre_right.push_back(pre[i]);
vin_right.push_back(vin[i]);
}
head->left=reConstructBinaryTree( pre_left,vin_left);
head->right=reConstructBinaryTree(pre_right,vin_right);c
return head;
}
};
5.用两个栈实现队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
解题思路:
一个栈用来入栈,另外一个栈用来出栈,当栈2为空时,栈1数据弹出到栈2
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 temp=stack2.top();
stack2.pop();
return temp;
}
private:
stack<int> stack1;
stack<int> stack2;
};
6.旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
解题思路:
二分法,题中意思为非递减数组,则可以分为两个有序数组
利用mid 获取 两个数组的边界 当left=mid或者大于mid时结束循环
注意 若有重复数字时 出现left =mid 直接使left向右移动 不然程序会卡住 只能移动left 移动right 会使最小数字被删除
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.size()==0)
{
return 0;
}
int left=0;
int right=rotateArray.size()-1;
while(left<right)
{
if(rotateArray[left]<rotateArray[right])
{
return rotateArray[left];
}
int mid=(left+right)/2;
if (rotateArray[left]<rotateArray[mid])
{
left=mid+1;
}
else if(rotateArray[left]>rotateArray[mid])
{
right=mid;
}
else{
left++;
}
}
return rotateArray[left];
}
};
7.斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n<=39
解题思路:
直接使用迭代 注意前三项值为0 1 1 然后直接使用前两项求和即可
class Solution {
public:
int Fibonacci(int n) {
if(n==0) return 0;
if(n==1||n==2) return 1;
int res=1;
int last=1;
for(int i=3;i<=n;i++)
{
int temp=res;
res=res+last;
last=temp;
}
return res;
}
};
8.跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
解题思路:
从顶向下递归
(1)假设台阶有n级 ,则到达第n级的方法有f(n)种
(2)当青蛙最后一步走一个台阶时,而达到最后一步之前则走了(n-1)级台阶,则此时达到n-1级时的方法有f(n-1)种
(3)当青蛙最后一步走二个台阶时,而达到最后一步之前则走了(n-2)级台阶,则此时达到n-2级时的方法有f(n-2)种
故走n级台阶的方法有f(n)=f(n-1)+f(n-2)
所以可以开始递归 递归结束条件设定:当n=1时 f(n)=1;当n=2时 f(n)=2 n–即可
class Solution {
public:
int jumpFloor(int number) {
if(number==0)
{
return 0;
}
if(number==1)
{
return 1;
}
if(number==2)
{
return 2;
}
return jumpFloor(number-1)+jumpFloor(number-2);
}
};
9.变态跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
解题思路:
假设台阶有n级 ,则到达第n级的方法有f(n)种
当第一次跳1级时 方法有f(1)种
当第一次跳2级时 若第一次跳一级台阶 则剩下 1级 则有f(2-1)种方法
若第一次跳二级台阶 则剩下 1级 则有f(2-2)种方法
当第一次跳3级时 若第一次跳一级台阶 则剩下 1级 则有f(3-1)种方法
若第一次跳二级台阶 则剩下 1级 则有f(3-2)种方法
若第一次跳三级台阶 则剩下 1级 则有f(3-3)种方法
则第一次跳n级时 共有f(n)=f(n-1)+…+f(1)
又 f(n-1)=f(n-2)+…+f(1)
所以 f(n)=2*f(n-1)
class Solution {
public:
int jumpFloorII(int number) {
if(number==0)
{
return 0;
}
if(number==1)
{
return 1;
}
if(number==2)
{
return 2;
}
return 2*jumpFloorII(number-1);
}
};
10.矩形覆盖
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
比如n=3时,2*3的矩形块有3种覆盖方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2O3efc1y-1596631268443)(C:\Users\ian\AppData\Roaming\Typora\typora-user-images\image-20200805105249149.png)]
解题思路:
假设 n种矩形有f(n)种解法
当n=1 解法为f(1)=1
当n=2 解法为f(2)=2
当n=3 则有两种情形 则为 f(n-1)+f(n-2)
class Solution {
public:
int rectCover(int number) {
if(number==0)
{
return 0;
}
if(number==1)
{
return 1;
}
if(number==2)
{
return 2;
}
return rectCover(number-1)+rectCover(number-2);
}
};
假设 n种矩形有f(n)种解法
当n=1 解法为f(1)=1
当n=2 解法为f(2)=2
当n=3 则有两种情形 则为 f(n-1)+f(n-2)
class Solution {
public:
int rectCover(int number) {
if(number==0)
{
return 0;
}
if(number==1)
{
return 1;
}
if(number==2)
{
return 2;
}
return rectCover(number-1)+rectCover(number-2);
}
};