二刷剑指——壹
作者:互联网
文章目录
- 1.[数组中重复的数字](https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/)
- 2.[二维数组中的查找](https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/)
- 3.[ 替换空格](https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/)
- 4.[从尾到头打印链表](https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/)
- 5.[重建二叉树](https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/)
- 6.[用两个栈实现队列](https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/)
- 7.[斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/)
- 8.[青蛙跳台阶问题](https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/)
- 9.[旋转数组的最小数字](https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/)
- 10.[矩阵中的路径](https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/)
1.数组中重复的数字
找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
方法1:
sort排序后,遍历数组,前面的值和后面的值相等即可
时间复杂度:nongn;
空间复杂度:快排需要递归,栈桢消耗 longn
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
sort(nums.begin(),nums.end());
int count=0;
for(int i=0;i<nums.size()-1;i++)
{
if(nums[i]==nums[i+1])
{
count=nums[i];
break;
}
}
return count;
}
};
方法2:
统计排序、找出统计数组之中,值大于1的选项,然后+1返回
时间复杂度:O(n);
空间复杂度: O(n);
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
vector<int> ret(nums.size(),0);
for(auto &e:nums)
{
if(ret[e]!=0)
return e;
ret[e]++;
}
return 0;
}
};
2.二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
时间复杂度:O(m*n)
空间复杂度:O(1)
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
if(matrix.size()==0)
return false;
int row=0;
int col=matrix[0].size()-1;
while(row>=0&&row<matrix.size()&&col>=0&&col<matrix[0].size())
{
if(matrix[row][col]>target)
col--;
else if(matrix[row][col]<target)
row++;
else
return true;
}
return false;
}
};
3. 替换空格
请实现一个函数,把字符串 s
中的每个空格替换成"%20"。
遍历s,遇到空格,则str+=“%20”,其余情况之下,+=s[i]
【注意:先开辟好str的空间,避免发生增容,导致发生拷贝】
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public:
string replaceSpace(string s) {
string str;
str.reserve(s.size());
for(int i=0;i<s.size();i++)
{
if(s[i]==' ')
str+="%20";
else
str+=s[i];
}
return str;
}
};
4.从尾到头打印链表
方法1:递归
链表天然具有递归属性
时间复杂度:O(N) 遍历整个链表
空间复杂度: O(N) 栈桢消耗n,返回数组n
class Solution {
public:
void _reversePrint(ListNode* head,vector<int> &ret)
{
if(head==NULL)
return ;
_reversePrint(head->next,ret);
ret.push_back(head->val);
}
vector<int> reversePrint(ListNode* head) {
vector<int> ret;
_reversePrint(head,ret);
return ret;
}
};
方法2:遍历reverse
遍历链表,将所有的内容添加至数组之中
然后将数组逆转
时间复杂度: O(N) 遍历整个链表
空间复杂度:O(N) 返回数组消耗
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
vector<int> ret;
ListNode* cur=head;
while(cur)
{
ret.push_back(cur->val);
cur=cur->next;
}
reverse(ret.begin(),ret.end());
return ret;
}
};
5.重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
在前序中找根节点,然后去中序之中寻找该根节点的位置,然后在中序之中判断该节点是否还有左右子树
时间复杂度:O(N^2):需要每次需要在中序之中遍历寻找根节点的位置
空间复杂度:O(N) 开辟N个节点空间、递归深度O(N)
class Solution {
public:
TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int &prev,int &inor_begin,int &inor_end)
{
if(prev>=preorder.size()||inor_begin>inor_end)
return NULL;
TreeNode *root=new TreeNode(preorder[prev]);//构造根节点
int start=inor_begin;
while(start<inor_end)
{
if(inorder[start]==preorder[prev])
break;
start++;
}
int end=start-1;
if(inor_begin<=end)//还有左区间
root->left= _buildTree(preorder,inorder,++prev,inor_begin,end);
else
root->left=NULL;
int begin=start+1;
if(begin<=inor_end)//还有右区间
root->right=_buildTree(preorder,inorder,++prev,begin,inor_end);
else
root->right=NULL;
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
//在前序中找根节点、找到后去中序遍历中找左右子树
int prev=0;
int inor_begin=0;
int inor_end=inorder.size()-1;
return _buildTree(preorder,inorder,prev,inor_begin,inor_end);
}
};
6.用两个栈实现队列
定义两个栈 -> st1、st2
入数据入到栈st1,当需要出数据的时候判断st2是否为空,不为空则直接从st2之中出
为空则将st1的全部内容倒过来,然后再出数据
class CQueue {
public:
CQueue() {}//自定义类型、自动调用构造函数
void appendTail(int value) {
st1.push(value);
}
int deleteHead() {
if(st2.empty())
{
while(!st1.empty())
{
st2.push(st1.top());
st1.pop();
}
}
if(st2.empty())
return -1;
int val=st2.top();
st2.pop();
return val;
}
stack<int> st1;
stack<int> st2;
};
7.斐波那契数列
方法1:递归法(超时)
方法2:三指针迭代法(first=1、second=0、third=0)
时间复杂度 :O(N)
空间复杂度:O(1)
class Solution {
public:
int fib(int n) {
int first=1;
int second=0;
int third=0;
for(int i=0;i<n;i++)
{
third=(first+second)%1000000007;
first=second;
second=third;
}
return third;
}
};
8.青蛙跳台阶问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
将题目转换一下就是: 1 1 2 3 5 斐波那契数列的斐波那契数列
class Solution {
public:
int numWays(int n) {
// 1 1 2 3 5 斐波那契数列
int first=0;
int second=1;
int third=1;
for(int i=0;i<n;i++)
{
third=(second+first)%1000000007;
first=second;
second=third;
}
return third;
}
};
9.旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
class Solution {
public:
int minArray(vector<int>& numbers) {
int left=0;
int right=numbers.size()-1;
while(left<right)
{
int mid=left+(right-left)/2;
if(numbers[mid]>numbers[right])
left=mid+1;
else if(numbers[mid]<numbers[right])
right=mid;
else//相等时
right--;
}
return numbers[left];
}
};
10.矩阵中的路径
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
深度搜索、回溯法:遍历搜索二维数组,找到第一个头节点之后,传入递归搜索函数,往四个方向进行搜索
标签:遍历,int,复杂度,ret,二刷,vector,数组 来源: https://blog.csdn.net/ych9527/article/details/116429097