剑指offer
- leetcode
- 剑指 Offer 03. 数组中重复的数字
- 剑指 Offer 04. 二维数组中的查找
- 剑指 Offer 05. 替换空格
- 剑指 Offer 06. 从尾到头打印链表
- 剑指 Offer 07. 重建二叉树
- 剑指 Offer 09. 用两个栈实现队列
- 剑指 Offer 10- I. 斐波那契数列
- 剑指 Offer 10- II. 青蛙跳台阶问题
- 剑指 Offer 11. 旋转数组的最小数字
- 剑指 Offer 12. 矩阵中的路径
- 剑指 Offer 13. 机器人的运动范围
- 剑指 Offer 14- I. 剪绳子
- 剑指 Offer 14- II. 剪绳子 II
- 剑指 Offer 15. 二进制中1的个数
- 剑指 Offer 16. 数值的整数次方
- 剑指 Offer 17. 打印从1到最大的n位数
- 剑指 Offer 18. 删除链表的节点
- 剑指 Offer 19. 正则表达式匹配**
- 剑指 Offer 20. 表示数值的字符串**
- 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
- 剑指 Offer 22. 链表中倒数第k个节点
- 剑指 Offer 24. 反转链表
- 剑指 Offer 25. 合并两个排序的链表
- 剑指 Offer 26. 树的子结构
- 剑指 Offer 27. 二叉树的镜像
- 剑指 Offer 28. 对称的二叉树
- 剑指 Offer 29. 顺时针打印矩阵
- 剑指 Offer 31. 栈的压入、弹出序列
- 剑指 Offer 32 - I. 从上到下打印二叉树
- 剑指 Offer 32 - II. 从上到下打印二叉树 II
- 剑指 Offer 32 - III. 从上到下打印二叉树 III
- 剑指 Offer 33. 二叉搜索树的后序遍历序列
- 剑指 Offer 35. 复杂链表的复制
- 剑指 Offer 36. 二叉搜索树与双向链表
leetcode
剑指 Offer 03. 数组中重复的数字
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
//把nums[i]放到下标为nums[i]的位置上
int n = nums.size();
int temp = 0;
for(int i = 0;i<n;i++)
{
if(nums[i] < 0 || nums[i] >= n) return -1;
else if(nums[i]!=i && nums[i] == nums[nums[i]]) return nums[i];
else if(nums[i]!=i && nums[i] != nums[nums[i]])
{
temp = nums[i]^nums[nums[i]];
nums[nums[i]] = temp^nums[nums[i]];
nums[i] = temp^nums[i];
}
}
return -1;
}
};
剑指 Offer 04. 二维数组中的查找
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
//从右上、左下开始搜索
int i = matrix.size()-1;
int j = 0;
while(i>=0 && j<matrix[0].size())
{
if(matrix[i][j] == target) return true;
else if(matrix[i][j] > target) i--;
else j++;
}
return false;
}
};
剑指 Offer 05. 替换空格
class Solution {
public:
string replaceSpace(string s) {
int num = 0;
for(int i = 0;i<s.size();i++)
{
if(s[i] == ' ') ++num;
}
int i = s.size()+num*2-1;
int j = s.size()-1;
s += string(num*2,' ');
while(i >= 0 && j >= 0)
{
if(s[j] != ' ')
s[i--] = s[j--];
else
{
s[i--] = '0';
s[i--] = '2';
s[i--] = '%';
j--;
}
}
return s;
}
};
剑指 Offer 06. 从尾到头打印链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
int num = 0;
ListNode* pNode = head;
while(pNode)
{
++num;
pNode = pNode->next;
}
vector<int> vec(num,0);
for(int i = num-1;i>=0;i--)
{
vec[i] = head->val;
head = head->next;
}
return vec;
}
};
剑指 Offer 07. 重建二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return build(preorder,0,inorder,0,inorder.size()-1);
}
TreeNode* build(vector<int>& preorder,int root,vector<int>& inorder,int start,int end)
{
if(start > end) return nullptr;
int i = start;
while(i<=end && inorder[i] != preorder[root]) i++;
TreeNode* node = new TreeNode(preorder[root]);
node->left = build(preorder,root+1,inorder,start,i-1);
node->right = build(preorder,root+i-start+1,inorder,i+1,end);
return node;
}
};
剑指 Offer 09. 用两个栈实现队列
class CQueue {
private:
stack<int> stk1;
stack<int> stk2;
public:
CQueue() {
}
void appendTail(int value) {
stk1.push(value);
}
int deleteHead() {
if(stk1.empty() && stk2.empty()) return -1;
if(stk2.empty())
{
while(!stk1.empty())
{
stk2.push(stk1.top());
stk1.pop();
}
}
int target = stk2.top();
stk2.pop();
return target;
}
};
/**
* Your CQueue object will be instantiated and called as such:
* CQueue* obj = new CQueue();
* obj->appendTail(value);
* int param_2 = obj->deleteHead();
*/
剑指 Offer 10- I. 斐波那契数列
class Solution {
public:
int fib(int n) {
vector<int> vec = {0,1};
for(int i = 2;i<=n;i++)
vec.push_back((vec[i-1]+vec[i-2])%1000000007);
return vec[n];
}
};
剑指 Offer 10- II. 青蛙跳台阶问题
class Solution {
public:
int numWays(int n) {
vector<int> dp = {1,1,2};
for(int i = 3;i<=n;i++)
dp.push_back( (dp[i-1]+dp[i-2])%1000000007 );
return dp[n];
}
};
剑指 Offer 11. 旋转数组的最小数字
class Solution {
public:
int minArray(vector<int>& numbers) {
int start = 0;
int end = numbers.size()-1;
while(start <= end)
{
int mid = start+(end-start)/2;
if(numbers[end] > numbers[mid]) end = mid;
else if(numbers[end] < numbers[mid]) start = mid+1;
else end--;
}
return numbers[start];
}
};
剑指 Offer 12. 矩阵中的路径
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
for(int i = 0;i<board.size();i++)
{
for(int j = 0;j<board[0].size();j++)
{
if( dfs(board,word,0,i,j) == true) return true;
}
}
return false;
}
bool dfs(vector<vector<char>>& board,string word,int index,int i,int j)
{
if(index == word.size()) return true;
if(i<0 || j<0 || i>=board.size() || j >= board[0].size()) return false;
if(board[i][j] != word[index]) return false;
board[i][j] = '*';
if( dfs(board,word,index+1,i,j+1) ||
dfs(board,word,index+1,i,j-1) ||
dfs(board,word,index+1,i+1,j) ||
dfs(board,word,index+1,i-1,j) ) return true;
board[i][j] = word[index];
return false;
}
};
剑指 Offer 13. 机器人的运动范围
class Solution {
public:
int movingCount(int m, int n, int k) {
vector<vector<int>> visit(m,vector<int>(n,0));
visit[0][0] = 1;
queue<pair<int,int>> q;
q.push({0,0});
int fx[2][2] = {1,0,0,1};
int num = 1;
while( !q.empty() )
{
auto temp = q.front();
q.pop();
for(int i = 0;i<2;i++)
{
int newx = temp.first + fx[i][0];
int newy = temp.second + fx[i][1];
if(newx>=0 && newy>=0 && newx<m && newy<n && visit[newx][newy]==0
&&sum(newx,newy)<=k)
{
num++;
q.push({newx,newy});
visit[newx][newy] = 1;
}
}
}
return num;
}
int sum(int x,int y)
{
int sum = 0;
while(x)
{
sum += (x%10);
x = x/10;
}
while(y)
{
sum += (y%10);
y = y/10;
}
return sum;
}
};
剑指 Offer 14- I. 剪绳子
class Solution {
public:
int cuttingRope(int n) {
if(n == 1) return 1;
if(n == 2 || n == 3) return n-1;
vector<int> dp(n+1,1);
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
for(int i = 4;i<=n;i++)
{
int maxValue = 1;
for(int j = 1;j<=i/2;j++)
{
maxValue = max(maxValue,dp[j]*dp[i-j]);
}
dp[i] = maxValue;
}
return dp[n];
}
};
剑指 Offer 14- II. 剪绳子 II
class Solution {
public:
int cuttingRope(int n) {
if(n == 1) return n;
if(n == 2 || n == 3) return n-1;
long long ans = 1;
while(n>4)
{
ans *= 3;
n -= 3;
ans = ans%1000000007;
}
return ans*n%1000000007;
}
};
剑指 Offer 15. 二进制中1的个数
class Solution {
public:
int hammingWeight(uint32_t n) {
int num = 0;
while(n)
{
n = n&(n-1);
++num;
}
return num;
}
};
剑指 Offer 16. 数值的整数次方
class Solution {
public:
double myPow(double x, int n) {
double ans = 1;
int nn = n;
while(n)
{
if(n&1 == 1) ans *= x;
n = n/2;
x *= x;
}
return nn>0 ? ans : 1/ans;
}
};
剑指 Offer 17. 打印从1到最大的n位数
class Solution {
public:
vector<int> printNumbers(int n) {
vector<int> ans;
int num = 1;
while(n)
{
num *= 10;
n -= 1;
}
for(int i = 0;i<(num-1);i++)
{
ans.push_back(i+1);
}
return ans;
}
};
剑指 Offer 18. 删除链表的节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if(val == head->val) return head->next;
ListNode* pHead = head;
ListNode* pNode = nullptr;
while(pHead->val != val)
{
pNode = pHead;
pHead = pHead->next;
}
pNode->next = pNode->next->next;
return head;
}
};
剑指 Offer 19. 正则表达式匹配**
class Solution {
public:
bool isMatch(string s, string p) {
int m = s.size();
int n = p.size();
auto matches = [&](int i, int j) {
if (i == 0) {
return false;
}
if (p[j - 1] == '.') {
return true;
}
return s[i - 1] == p[j - 1];
};
vector<vector<int>> f(m + 1, vector<int>(n + 1));
f[0][0] = true;
for (int i = 0; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (p[j - 1] == '*') {
f[i][j] |= f[i][j - 2];
if (matches(i, j - 1)) {
f[i][j] |= f[i - 1][j];
}
}
else {
if (matches(i, j)) {
f[i][j] |= f[i - 1][j - 1];
}
}
}
}
return f[m][n];
}
};
剑指 Offer 20. 表示数值的字符串**
class Solution {
private:
// 整数的格式可以用[+|-]B表示, 其中B为无符号整数
bool scanInteger(const string s, int& index){
if(s[index] == '+' || s[index] == '-')
++index;
return scanUnsignedInteger(s, index);
}
bool scanUnsignedInteger(const string s, int& index){
int befor = index;
while(index != s.size() && s[index] >= '0' && s[index] <= '9')
index ++;
return index > befor;
}
public:
// 数字的格式可以用A[.[B]][e|EC]或者.B[e|EC]表示,
// 其中A和C都是整数(可以有正负号,也可以没有),而B是一个无符号整数
bool isNumber(string s) {
if(s.size() == 0)
return false;
int index = 0;
//字符串开始有空格,可以返回true
while(s[index] == ' ') //书中代码没有该项测试
++index;
bool numeric = scanInteger(s, index);
// 如果出现'.',接下来是数字的小数部分
if(s[index] == '.'){
++index;
// 下面一行代码用||的原因:
// 1. 小数可以没有整数部分,例如.123等于0.123;
// 2. 小数点后面可以没有数字,例如233.等于233.0;
// 3. 当然小数点前面和后面可以有数字,例如233.666
numeric = scanUnsignedInteger(s, index) || numeric;
}
// 如果出现'e'或者'E',接下来跟着的是数字的指数部分
if(s[index] == 'e' || s[index] == 'E'){
++index;
// 下面一行代码用&&的原因:
// 1. 当e或E前面没有数字时,整个字符串不能表示数字,例如.e1、e1;
// 2. 当e或E后面没有整数时,整个字符串不能表示数字,例如12e、12e+5.4
numeric = numeric && scanInteger(s ,index);
}
//字符串结尾有空格,可以返回true
while(s[index] == ' ')
++index;
cout << s.size() << " " << index; //调试用
return numeric && index == s.size();
}
};
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
class Solution {
public:
vector<int> exchange(vector<int>& nums) {
int i = 0;
int j = nums.size()-1;
while(i<j)
{
while(nums[i]%2 == 1 && i<j) ++i;
while(nums[j]%2 == 0 && i<j) --j;
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
++i;
--j;
}
return nums;
}
};
剑指 Offer 22. 链表中倒数第k个节点
剑指 Offer 24. 反转链表
剑指 Offer 25. 合并两个排序的链表
剑指 Offer 26. 树的子结构
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSubStructure(TreeNode* A, TreeNode* B) {
if(A == nullptr || B == nullptr) return false;
return isSub(A,B) || isSubStructure(A->left,B)
|| isSubStructure(A->right,B);
}
bool isSub(TreeNode* A,TreeNode* B)
{
if(B == nullptr) return true;
if(A == nullptr) return false;
if(A->val == B->val)
return isSub(A->left,B->left)&&isSub(A->right,B->right);
else
return false;
}
};
剑指 Offer 27. 二叉树的镜像
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if(root == nullptr) return nullptr;
if(root->left == nullptr && root->right == nullptr) return root;
TreeNode* node = new TreeNode(root->val);
node->left = mirrorTree(root->right);
node->right = mirrorTree(root->left);
return node;
}
};
剑指 Offer 28. 对称的二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
return is(root->left,root->right);
}
bool is(TreeNode* left,TreeNode* right)
{
if(left == nullptr && right == nullptr) return true;
if(left == nullptr || right == nullptr) return false;
if(left->val != right->val) return false;
return is(left->left,right->right) && is(left->right,right->left);
}
};
剑指 Offer 29. 顺时针打印矩阵
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if(matrix.empty()) return {};
int top = 0;
int bottom = matrix.size()-1;
int left = 0;
int right = matrix[0].size()-1;
vector<int> ans;
while(1)
{
for(int i = left;i<=right;i++)
ans.push_back(matrix[top][i]);
top++;
if(top>bottom) break;
for(int i = top;i<=bottom;i++)
ans.push_back(matrix[i][right]);
right--;
if(right<left) break;
for(int i = right;i>=left;i--)
ans.push_back(matrix[bottom][i]);
bottom--;
if(bottom<top) break;
for(int i = bottom;i>=top;i--)
ans.push_back(matrix[i][left]);
left++;
if(left>right) break;
}
return ans;
}
};
剑指 Offer 31. 栈的压入、弹出序列
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
stack<int> s;
int j = 0;
for(int i = 0;i<pushed.size();i++)
{
s.push(pushed[i]);
while(!s.empty() && s.top()==popped[j] )
{
s.pop();
j++;
}
}
return s.empty();
}
};
剑指 Offer 32 - I. 从上到下打印二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> levelOrder(TreeNode* root) {
if(root == nullptr) return {};
queue<TreeNode* > q;
vector<int> ans;
q.push(root);
while( !q.empty())
{
TreeNode* node = q.front();
q.pop();
ans.push_back(node->val);
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
return ans;
}
};
剑指 Offer 32 - II. 从上到下打印二叉树 II
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
if(root == nullptr) return {};
vector<vector<int>> ans;
queue<TreeNode* > q;
q.push(root);
while(!q.empty())
{
int size = q.size();
vector<int> vec;
while(size)
{
TreeNode* node = q.front();
q.pop();
vec.push_back(node->val);
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
size--;
}
ans.push_back(vec);
}
return ans;
}
};
剑指 Offer 32 - III. 从上到下打印二叉树 III
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
if(root == nullptr) return {};
vector<vector<int>> ans;
deque<TreeNode* > dq;
dq.push_back(root);
int flag = 1;
while(!dq.empty())
{
int size = dq.size();
vector<int> vec;
while(size)
{
if(flag == 1)
{
TreeNode* node = dq.front();
dq.pop_front();
vec.push_back(node->val);
if(node->left) dq.push_back(node->left);
if(node->right) dq.push_back(node->right);
}
else
{
TreeNode* node = dq.back();
dq.pop_back();
vec.push_back(node->val);
if(node->right) dq.push_front(node->right);
if(node->left) dq.push_front(node->left);
}
size--;
}
ans.push_back(vec);
flag = -flag;
}
return ans;
}
};
剑指 Offer 33. 二叉搜索树的后序遍历序列
class Solution {
public:
bool verifyPostorder(vector<int>& postorder) {
return is(postorder,0,postorder.size()-1);
}
bool is(vector<int>& postorder,int left,int right)
{
if(left>=right) return true;
int root = right;
int i = left;
while(i<right && postorder[i]<postorder[right])
i++;
for(int j = i;j<right;j++)
if(postorder[j] < postorder[root])
return false;
return is(postorder,left,i-1) && is(postorder,i,right-1);
}
};
剑指 Offer 35. 复杂链表的复制
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if(head == nullptr) return nullptr;
Node* pHead = head;
//复制
while(head)
{
Node* node = new Node(head->val);
node->next = head->next;
head->next = node;
head = node->next;
}
head = pHead;
while(head)
{
if(head->random) head->next->random = head->random->next;
head = head->next->next;
}
//拆开
head = pHead;
pHead = head->next;
Node* node = pHead;
while(head)
{
head->next = head->next->next;
if(node->next) node->next = node->next->next;
head = head->next;
node = node->next;
}
return pHead;
}
};
剑指 Offer 36. 二叉搜索树与双向链表
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node() {}
Node(int _val) {
val = _val;
left = NULL;
right = NULL;
}
Node(int _val, Node* _left, Node* _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
private:
Node* pre,*head;
public:
Node* treeToDoublyList(Node* root) {
if(root == nullptr) return nullptr;
dfs(root);
head->left = pre;
pre->right = head;
return head;
}
void dfs(Node* cur)
{
if(cur == nullptr)
return ;
dfs(cur->left);
if(pre == nullptr)
head = cur;
else
pre->right = cur;
cur->left = pre;
pre = cur;
dfs(cur->right);
return ;
}
};