二叉树
给你一个二叉树的根节点 root ,返回其最大路径和
class Solution {
private:
int ans=INT_MIN;
public:
int maxNodeGain(TreeNode* root)
{
if(root==nullptr)
return 0;
int left = max(0,maxNodeGain(root->left));
int right = max(0,maxNodeGain(root->right));
int maxNodePath = left + right + root->val;
ans = max(ans,maxNodePath);
return max(left,right)+root->val;
}
int maxPathSum(TreeNode* root) {
maxNodeGain(root);
return ans;
}
};
数组中重复的数字
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int n = nums.size();
for(int i = 0; i < n; i++){
int k = nums[i];
if(k < 0) k += n;
if(nums[k] < 0) return k;
nums[k] -= n;
}
return -1;
}
};
二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
if(matrix.empty())
{
return 0;
}
int n=matrix.size();//行
int m=matrix[0].size();//如果不加上面的empty,这边的matrix[0]就会内存溢出
int i=n-1;
int j=0;
while((i>=0)&&(j<m))
{
int num=matrix[i][j];
//cout<<num;
if(target<num)
{
i--;
}
else if(target>num)
j++;
else return true;
}
return false;
/*int i = matrix.size() - 1, j = 0;
while(i >= 0 && j < matrix[0].size())//这种情况下空矩阵的时候,执行完i>=0就会退出,不会执行后面的语句
{
if(matrix[i][j] > target) i--;
else if(matrix[i][j] < target) j++;
else return true;
}
return false;*/
}
};
替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
思路:先计算有多少个字符,再找出有多少个空格,空格变成%20后,长度会增加,从后面开始往前遍历
class Solution {
public:
string replaceSpace(string s) {
int count=0,len=s.size();
for(char c:s)
{
if(c==' ')
count++;
}
s.resize(len+2*count);
for(int i=len-1,j=s.size()-1;i<j;i--,j--)
{
if(s[i]!=' ')
s[j]=s[i];
else
{
s[j-2]='%';
s[j-1]='2';
s[j]='0';
j-=2;
}
}
return s;
}
};
从头到尾打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
解一:反转
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
vector<int> res;
while(head){
res.push_back(head->val);
head=head->next;
}
reverse(res.begin(),res.end());
return res;
}
};
解二:堆栈
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
vector<int> res;
stack<int> s;
while(head)
{
s.push(head->val);
head=head->next;
}
while(!s.empty())
{
res.push_back(s.top());
s.pop();
}
return res;
}
};
重建二叉树
重建二叉树:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
递归
class Solution {
private:
unordered_map<int, int> index;
public:
TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
if (preorder_left > preorder_right) {
return nullptr;
}
// 前序遍历中的第一个节点就是根节点
int preorder_root = preorder_left;
// 在中序遍历中定位根节点
int inorder_root = index[preorder[preorder_root]];
// 先把根节点建立出来
TreeNode* root = new TreeNode(preorder[preorder_root]);
// 得到左子树中的节点数目
int size_left_subtree = inorder_root - inorder_left;
// 递归地构造左子树,并连接到根节点
// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
// 递归地构造右子树,并连接到根节点
// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
// 构造哈希映射,帮助我们快速定位根节点
for (int i = 0; i < n; ++i) {
index[inorder[i]] = i;
}
return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
}
};
用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
class CQueue {
stack<int> stack1,stack2;
public:
CQueue() {
while(!stack1.empty())
{
stack1.pop();
}
while(!stack2.empty())
{
stack2.pop();
}
}
void appendTail(int value) {
stack1.push(value);
}
int deleteHead() {
if(stack2.empty())
{
while(!stack1.empty())
{
stack2.push(stack1.top());
stack1.pop();
}
}
if(stack2.empty())
{
return -1;
}
else
{
int deletenum = stack2.top();
stack2.pop();
return deletenum;
}
}
};
剑指offer10-1
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
class Solution {
public:
int fib(int n) {
int m=0;
if(n==0)return 0;
if(n==1)return 1;
int a=0,b=1;
if(n>1)
{
for(int i=1;i<n;i++)
{
int temp=a%1000000007;
a=b%1000000007;
b=(a+temp)%1000000007;
}
}
return b;
}
};
剑指offer10-2
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
本质还是斐波那契数列问题
class Solution {
public:
int numWays(int n) {
if(n==0||n==1)return 1;
int a=1,b=1,c=0;
if(n>1)
{
for(int i=1;i<n;i++)
{
c=(a+b)%1000000007;
a=b;
b=c;
}
}
return c;
}
};
旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
class Solution {
public:
int minArray(vector<int>& numbers) {
int j=0;
//cout<<numbers.size();
for(int i=0;i<numbers.size()-1;i++)
{
if(numbers[i]>numbers[i+1])
{
j =i+1;
}
}
// cout<<j;
return numbers[j];
}
};