文章目录
- [剑指 Offer 04. 二维数组中的查找](https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/)
- [剑指 Offer 07. 重建二叉树](https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/)
- [剑指 Offer 09. 用两个栈实现队列](https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/)
- [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/)
- [剑指 Offer 12. 矩阵中的路径](https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/)
- [剑指 Offer 13. 机器人的运动范围](https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/)
- [剑指 Offer 14- I. 剪绳子](https://leetcode-cn.com/problems/jian-sheng-zi-lcof/)
- [剑指 Offer 14- II. 剪绳子 II](https://leetcode-cn.com/problems/jian-sheng-zi-ii-lcof/)
- [剑指 Offer 16. 数值的整数次方](https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/)
- [剑指 Offer 20. 表示数值的字符串](https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/)
- [剑指 Offer 25. 合并两个排序的链表](https://leetcode-cn.com/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof/)
- [剑指 Offer 30. 包含min函数的栈](https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/)
- [剑指 Offer 31. 栈的压入、弹出序列](https://leetcode-cn.com/problems/zhan-de-ya-ru-dan-chu-xu-lie-lcof/)
- [剑指 Offer 33. 二叉搜索树的后序遍历序列](https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/)
- [剑指 Offer 35. 复杂链表的复制](https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/)
- [剑指 Offer 46. 把数字翻译成字符串](https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/)
- [剑指 Offer 48. 最长不含重复字符的子字符串](https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/)
剑指 Offer 04. 二维数组中的查找
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
if (matrix.size() == 0) return false;
int n = matrix.size(), m = matrix[0].size();
int row = 0, column = m - 1;
while (row < n && column >= 0) {
if (matrix[row][column] == target) {
return true;
}
if (matrix[row][column] < target) {
row++;
} else {
column--;
}
}
return false;
}
};
剑指 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:
unordered_map<int, int> mp;
TreeNode* BuildNewTree(vector<int>& preorder, vector<int>& inorder, int pre_left, int pre_right, int in_left, int in_right) {
if (pre_left > pre_right) {
return NULL;
}
TreeNode* node = new TreeNode(preorder[pre_left]);
int index = mp[node->val];
int pre_left_size = index - in_left;
node->left = BuildNewTree(preorder, inorder, pre_left + 1, pre_left + pre_left_size, in_left, index - 1);
node->right = BuildNewTree(preorder, inorder, pre_left_size + pre_left + 1, pre_right, index + 1, in_right);
return node;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int len = preorder.size();
for (int i = 0; i < len; i++) {
mp[inorder[i]] = i;
}
return BuildNewTree(preorder, inorder, 0, len - 1, 0, len - 1);
}
};
剑指 Offer 09. 用两个栈实现队列
class CQueue {
public:
stack<int> stack1;
stack<int> stack2;
CQueue() {
}
void appendTail(int value) {
stack1.push(value);
}
int deleteHead() {
int ret = -1;
if (stack2.empty()) {
while (!stack1.empty()) {
int temp = stack1.top();
stack2.push(temp);
stack1.pop();
}
}
if (stack2.empty()) {
return ret;
}
ret = stack2.top();
stack2.pop();
return ret;
}
};
/**
* 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) {
int MOD = 1000000007;
if (n <= 1) {
return n;
}
// return fib(n - 1) + fib(n - 2);
int a = 0, b = 1 , c;
for (int i = 2; i <= n; i ++) {
c = (a + b) % 1000000007;
a = b;
b = c;
}
return c;
}
};
剑指 Offer 12. 矩阵中的路径
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
rows = board.size();
cols = board[0].size();
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
if(dfs(board, word, i, j, 0)) return true;
}
}
return false;
}
private:
int rows, cols;
bool dfs(vector<vector<char>>& board, string word, int i, int j, int k) {
if(i >= rows || i < 0 || j >= cols || j < 0 || board[i][j] != word[k]) return false;
if(k == word.size() - 1) return true;
board[i][j] = '\0';
bool res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) ||
dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);
board[i][j] = word[k];
return res;
}
};
剑指 Offer 13. 机器人的运动范围
class Solution {
public:
int ret = 0;
int countnum (int row, int column) {
int count = 0;
while(row) {
count += row % 10;
row /= 10;
}
while (column) {
count += column % 10;
column /= 10;
}
return count;
}
void dfs(int i, int j, int m, int n, int k, vector<vector<int>> &mp) {
if (i >= m || j >= n) {
return;
}
if (countnum(i, j) > k || mp[i][j] == -1) {
mp[i][j] = -1;
return ;
}
mp[i][j] = -1;
ret++;
if (mp[i + 1][j] != -1) {
dfs(i + 1, j ,m, n, k, mp);
}
if (mp[i][j +1] != -1) {
dfs(i, j + 1, m, n, k, mp);
}
}
int movingCount(int m, int n, int k) {
//dfs
vector<vector<int>> mp(m + 1, vector<int>(n + 1, 0));
dfs(0, 0, m, n, k, mp);
return ret;
}
};
剑指 Offer 14- I. 剪绳子
class Solution {
public:
int cuttingRope(int n) {
//dp[i] = max(前面保持不动,cur长度取1 ; 长度取j, 前面长度为i-j ; 长度取j, 前面为dp[i - j])
//为什么i-j 和dp[i-j]不冲突,因为m>1,所以dp[i-j]代表里面剪了,i-j代表没剪
vector<int> dp(n + 1);
int cur_max;
for (int i = 2; i <= n; i++) {
cur_max = 0;
for (int j = 1; j <= i; j++) {
cur_max = max({cur_max,j * (i - j), j * dp[i - j] });
}
dp[i] = cur_max;
}
return dp[n];
}
};
剑指 Offer 14- II. 剪绳子 II
class Solution {
public:
int cuttingRope(int n) {
if (n <= 3) return n - 1;
int MOD = 1000000007;
long ret = 1;
if (n % 3 == 1) { //3 * 1 < 4
ret = 4;
n = n - 4;
}
if (n % 3 == 2) {
ret = 2;
n = n - 2;
}
while (n) {
n = n - 3;
ret = ret * 3 % MOD;
}
return ret;
}
};
剑指 Offer 16. 数值的整数次方
class Solution {
public:
double myPow(double x, int n) {
//用二进制想问题 11(3)、2^10
double ret = 1.0;
for (int i = n; i != 0; i /= 2) {
if (i % 2 != 0) {
ret *= x;
}
x *= x;
}
return n >= 0 ? ret : 1 / ret;
}
};
剑指 Offer 20. 表示数值的字符串
class Solution {
public:
bool isNumber(string s) {
//正则表达式 确定有限状态自动机(DFA)
// 空格 +/- 数字 . E/e
int tansfer[9][5] = {
{0, 1, 2, 4, -1},
{-1, -1, 2, 4, -1},
{8, -1, 2, 3, 5},
{8, -1, 3, -1, 5},
{-1, -1, 3, -1, -1},
{-1, 6, 7, -1, -1},
{-1, -1, 7, -1, -1},
{8, -1, 7, -1, -1},
{8, -1, -1, -1, -1}
};
int state = 0;
for (char ch : s) {
if (ch == ' ') state = tansfer[state][0];
else if (ch == '+' || ch == '-') state = tansfer[state][1];
else if (isdigit(ch)) state = tansfer[state][2];
else if (ch == '.') state = tansfer[state][3];
else if (ch == 'E' || ch == 'e') state = tansfer[state][4];
else state = -1;
if (state == -1) return false;
}
return state == 2 || state == 3 || state == 7 || state == 8;
}
};
剑指 Offer 25. 合并两个排序的链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* begin = new ListNode(-1), *index = begin;
ListNode* index_l1 = l1, *index_l2 = l2;
while (index_l1 != NULL && index_l2 != NULL) {
if (index_l1->val < index_l2->val) {
index->next = index_l1;
index = index->next;
index_l1 = index_l1->next;
} else {
index->next = index_l2;
index = index->next;
index_l2 = index_l2->next;
}
}
if (index_l1 != NULL) {
index->next = index_l1;
}
if (index_l2 != NULL) {
index->next = index_l2;
}
return begin->next;
}
};
剑指 Offer 30. 包含min函数的栈
class MinStack {
public:
stack<int> sk;
stack<int> sk_m;
/** initialize your data structure here. */
MinStack() {
sk_m.push(INT_MAX);
}
void push(int x) {
sk.push(x);
sk_m.push(std::min(x, sk_m.top()));
}
void pop() {
sk.pop();
sk_m.pop();
}
int top() {
return sk.top();
}
int min() {
return sk_m.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->min();
*/
剑指 Offer 31. 栈的压入、弹出序列
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
int len = pushed.size(), index = 0;
// vector<int> mp;
// for (int i = 0; i < len; i++) {
// mp[pushed[i]] = i;
// }
// for (auto& ch : popped) {
// }
stack<int> sk;
for (int i = 0; i < len; i++) {
sk.push(pushed[i]);
while (index < len && !sk.empty() && popped[index] == sk.top()) {
index++;
sk.pop();
}
}
return index == len ? true : false;
}
};
剑指 Offer 33. 二叉搜索树的后序遍历序列
class Solution {
public:
bool verifyPostorder(vector<int>& postorder) {
int root = INT_MAX;
stack<int> sk;
for (int i = postorder.size() - 1; i >= 0; i--) {
if (postorder[i] > root) { //如果左子树大于root 判false
return false;
}
while (!sk.empty() && postorder[i] < sk.top()) { //如果比直接根节点小 则右边的节点pop 直接根节点作为root
root = sk.top();
sk.pop();
}
sk.push(postorder[i]); // 其他子树入栈,右子树直接入栈
}
return true;
}
};
剑指 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:
unordered_map<Node*, Node*> mp;
Node* copyRandomList(Node* head) {
//递归加哈希
if (head == NULL) {
return NULL;
}
if (!mp.count(head)) {
Node* node = new Node(head->val);
mp[head] = node;
node->next = copyRandomList(head->next);
node->random = copyRandomList(head->random);
}
return mp[head];
}
};
剑指 Offer 46. 把数字翻译成字符串
class Solution {
public:
int translateNum(int num) {
//dp[i] = dp[i-1] + substr(string(dp[i - 1] + dp[i]) < 26 ? dp[i - 2] : 0;
string ans = to_string(num);
vector<int> dp(ans.size() + 1);
dp[0] = 1;
if (ans.substr(0, 2) <= "25" && ans.substr(0, 2) >= "10") {
dp[1] = 2;
} else {
dp[1] = 1;
}
for (int i = 2; i < ans.size(); i++) {
if (ans.substr(i - 1, 2) <= "25" && ans.substr(i - 1, 2) >= "10") {
dp[i] = dp[i - 1] + dp[i - 2];
} else {
dp[i] = dp[i - 1];
}
}
return dp[ans.size() - 1];
}
};
剑指 Offer 48. 最长不含重复字符的子字符串
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//dp
//dp[i]记录包含当前节点最长的子串
//dp[i] = dp[i - 1] + 1 (不重复)
//j = mp[s[i]] dp[i] = j - i
int len = s.length();
vector<int> dp(len, 0);
unordered_map<char, int> mp;
int ret = 0;
for (int i = 0; i < len; i++) {
if (i == 0) {
dp[i] = 1;
} else if (!mp.count(s[i])) {
dp[i] = dp[i - 1] + 1;
} else {
int j = mp[s[i]];
if (i - j > dp[i - 1]) {
dp[i] = dp[i - 1] + 1;
} else {
dp[i] = i - j;
}
}
mp[s[i]] = i;
ret = max(ret, dp[i]);
}
return ret;
}
};