剑指offer(第二版)
1.二维数组中的查找
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int row=array.size()-1;
int cul=0;
if(array.size()==0) return false;
while(row >= 0 && cul < array[0].size())
{
int k=array[row][cul];
if(k==target) return true;
else if(k>target) row--;
else cul++;
}
return false;
}
2.数组中的重复数字
描述:输出数组中的重复数字,如果没有,返回-1
int duplicate(vector<int>& numbers) {
unordered_map<int, int> map;
for(auto i:numbers)
{
map[i]++;
}
for(int i=0;i<map.size();i++)
{
if(map[i]>1)
return i;
}
return -1;
}
3.替换空格
string replaceSpace(string s) {
string str=""
for(int i=0
{
if(s[i]==' ')
{
str+=('%')
str+=('2')
str+=('0')
}
else str+=s[i]
}
return str
}
4.从尾到头打印链表
思路:定义一个数组接收所有节点的权值,反转数组并返回
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> v;
while(head)
{
v.push_back(head->val);
head=head->next;
}
reverse(v.begin(), v.end());
return v;
}
5.重建二叉树
描述:给出一棵树的前序遍历和中序遍历数组,重建出这颗二叉树
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
return rebuild(pre, 0, pre.size()-1, vin, 0, vin.size()-1);
}
TreeNode* rebuild(vector<int>& pre, int pre_left, int pre_right,
vector<int>& vin, int vin_left, int vin_right)
中序遍历数组,前序遍历数组左下标,右下标
{
if (pre_left > pre_right||vin_left > vin_right) return nullptr;
TreeNode* root = new TreeNode(pre[pre_left]);
for (int i=vin_left; i<=vin_right; ++i)
{
if (vin[i] == root->val) {
root->left = rebuild(pre, pre_left+1, pre_left+i-vin_left,
vin, vin_left, i-1);
root->right = rebuild(pre, pre_left+i-vin_left+1, pre_right,
vin, i+1, vin_right);
break;
}
}
return root;
}
6.二叉树的下一个节点
描述:给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。
法一:暴力法
void in_order(TreeLinkNode * root, vector<TreeLinkNode*> &v)//中序递归遍历函数
{
if(!root) return
in_order(root->left, v)
v.push_back(root)
in_order(root->right, v)
}
TreeLinkNode* GetNext(TreeLinkNode* pNode) {
TreeLinkNode * root = nullptr
TreeLinkNode * tmp = pNode
while(tmp) //求出整棵树的根节点
{
root=tmp
tmp=tmp->next
}
vector<TreeLinkNode*> v
in_order(root, v)
for(int i=0
{
if(v[i]==pNode && i+1!=v.size()) return v[i+1]
}
return nullptr
}
法二:最优解法
牢牢抓住中序遍历左根右的核心思想寻找下一节点
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if (!pNode) return pNode;
if (pNode->right)
{
pNode = pNode->right;
while (pNode->left)
{
pNode = pNode->left;
}
return pNode;
}
while (pNode->next)
{
TreeLinkNode *root = pNode->next;
if (root->left == pNode)
{
return root;
}
pNode = pNode->next;
}
return nullptr;
}
7.用两个栈实现队列
注意:pop操作需要分类,若stack2中没有元素,才要stack2.push(stack1.top());
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 ret=stack2.top();
stack2.pop();
return ret;
}
private:
stack<int> stack1;
stack<int> stack2;
};
8.斐波那契数列
时间复杂度O(n),空间复杂度O(1)
int Fibonacci(int n) {
int a = 1 , b = 1 , c = 1;
for (int i = 3 ; i <= n ; i ++) {
c = a+b , a = b , b = c;
}
return c;
}