1. 剑指 Offer 03. 数组中重复的数字 力扣
class Solution {
public:
int findRepeatNumber(vector& nums) {
/* 法一 排序 */
/* 法二 哈希表 */
map mymap;
int size = nums.size();
mymap[nums[0]] = 0;
for(int i= 1; i < size; ++i) {
if (mymap.find(nums[i]) == mymap.end()) {
mymap[nums[i]] = i;
} else {
return nums[i];
}
}
return 0;
/* 法3 方法3: 鸽巢原理,因为出现的元素值 < nums.size(); 所以我们可以将见到的元素 放到索引的位置,如果交换时,发现索引处已存在该元素,则重复 O(N) 空间O(1) */
for(int i=0;i
2. 剑指 Offer 04. 二维数组中的查找 力扣
class Solution {
public:
bool findNumberIn2DArray(vector>& matrix, int target) {
int rows = matrix.size();
if (rows == 0) {
return false;
}
int cols = matrix[0].size();
if (cols == 0) {
return false;
}
int row = 0;
int col = cols - 1;
while(row < rows && col >= 0) {
if (matrix[row][col] == target) {
return true;
}
else if (matrix[row][col] < target) {
row++;
}
//这里必须加else if 否则上面row++后会越界
else if (matrix[row][col] > target) {
col--;
}
}
return false;
}
};
3. 剑指 Offer 05. 替换空格 力扣
class Solution {
public:
string replaceSpace(string s) {
int len = s.size();
string res;
if (len == 0 || len > 10000) {
return res;
}
int cur = 0;
while(cur < len) {
string tmp = "";
while(cur < len && s[cur] != ' ') {
tmp += s[cur];
cur++;
}
res += tmp;
if (s[cur] == ' ') {
res += "%20";
}
cur++;
}
return res;
}
};
4. 剑指 Offer 06. 从尾到头打印链表 力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void dfs(ListNode* head, vector& res) {
if (!head) {
return;
}
dfs(head -> next, res);
if (head) {
res.push_back(head -> val);
}
}
vector reversePrint(ListNode* head) {
//法一:栈
//法二:递归
vector res;
dfs(head, res);
return res;
}
};
5. 剑指 Offer 09. 用两个栈实现队列 力扣
两个栈,一个栈负责进入,一个栈负责出 当有元素进入,第一个栈后面加入 当有元素出队列时候,三种情况 1.两个栈都是空,则证明是空队列 2.第一个栈有元素,第二个栈没有元素,把第一栈的元素全部出栈放入第二个栈,第二个栈出栈 3.第二个栈还有元素,第二个栈出栈
class CQueue {
public:
stack sta1;
stack sta2;
CQueue() {
}
void appendTail(int value) {
sta1.push(value);
}
int deleteHead() {
if (sta1.empty() && sta2.empty()) {
return -1;
}
if (!sta2.empty()) {
int top = sta2.top();
sta2.pop();
return top;
} else {
while(!sta1.empty()) {
sta2.push(sta1.top());
sta1.pop();
}
int top = sta2.top();
sta2.pop();
return top;
}
return -1;
}
};
/**
* Your CQueue object will be instantiated and called as such:
* CQueue* obj = new CQueue();
* obj->appendTail(value);
* int param_2 = obj->deleteHead();
*/
6. 剑指 Offer 13. 机器人的运动范围 力扣
class Solution {
public:
/* 注意下这题dfs上下左右后,用不用把visit[i][j]再赋false */
int CountSum(int m, int n) {
int sum = 0;
while(m > 0) {
sum += m % 10;
m /= 10;
}
while(n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
int dfs(int i, int j, int m, int n, vector>& visit, int k) {
if (i < 0 || j < 0 || i >= m || j >= n || visit[i][j] == true || CountSum(i, j) > k ) {
return 0;
}
visit[i][j] = true;
return 1 + dfs(i + 1, j, m, n, visit, k) + dfs(i - 1, j, m, n, visit, k) + dfs(i, j + 1, m, n, visit, k) + dfs(i, j - 1, m, n, visit, k);
}
int movingCount(int m, int n, int k) {
vector> visit(m, vector(n, false));
return dfs(0, 0, m, n, visit, k);
}
};
7. 剑指 Offer 15. 二进制中1的个数 力扣
class Solution {
public:
int hammingWeight(uint32_t n) {
//n&(-n)得到n的最后一位的1
//n&(n-1) 去除 n 的位级表示中最低的那一位 1
//位运算理论https://www.cnblogs.com/nobita/p/14320239.html
int count = 0;
while(n) {
n = n & (n - 1);
count++;
}
return count;
}
};
8. 剑指 Offer 16. 数值的整数次方 力扣
class Solution {
public:
//如果n是奇数,x的n/2次方乘以x的n/2次方乘以x
//若n是偶数,x的n/2次方乘以x的n/2次方
//若n是负数怎么办
/* -2.00000 -2147483648会出错,原因是-2147483648超出int范围,可以直接在原题的函数参数double myPow(double x, int n)里的int n 改成long n 因为用例里哪怕是int类型支持转成long类型*/
double myPow(double x, long n/* 题原本是int n */) {
if (n == 0) {
return 1.0;
}
if (n == 1) {
return x;
}
if (x == 1.00) {
return x;
}
if (n < 0) {
x = 1/x;
n = -n;
}
double res = 1.0;
double tmp = myPow(x, abs(n) >> 1);
if (abs(n) % 2 == 1) {
res = tmp * tmp * x;
} else {
res = tmp * tmp;
}
if (n > 0) {
return res;
} else {
return 1.0 / res;
}
return res;
}
};
9. 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 力扣
class Solution {
public:
vector exchange(vector& nums) {
int len = nums.size();
if (len == 0) {
return nums;
}
int left = 0;
int right = len - 1;
while(left <= right) {
while(left < len && nums[left] % 2 == 1) {
left++;
}
while(right >= 0 && nums[right] % 2 == 0) {
right--;
}
if (left <= right) {
swap(nums[left], nums[right]);
left++;
right--;
}
}
return nums;
}
};
10. 剑指 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 compareTwoTrees(TreeNode* A, TreeNode* B) {
if (B == nullptr) {
return true;
}
if (A == nullptr) { /*if (A == nullptr && B != nullptr)*/
return false;
}
if (A -> val != B -> val) {
return false;
}
return compareTwoTrees(A -> left, B -> left) && compareTwoTrees(A -> right, B -> right);
}
bool isSubStructure(TreeNode* A, TreeNode* B) {
if (B == nullptr) {
return false;
}
if (A == nullptr) {
return false;
}
return isSubStructure(A -> left, B) || isSubStructure(A -> right, B) || compareTwoTrees(A, B);
}
};
11. 反转链表力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
/* if (head == nullptr || head -> next == nullptr) {
return head;
}
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* tmp_next = nullptr;
while(cur) {
tmp_next = cur -> next;
cur -> next = pre;
pre = cur;
cur = tmp_next;
}
return pre; */
if (head == nullptr || head -> next == nullptr) {
return head;
}
ListNode* tmp = reverseList(head -> next);
head -> next -> next = head;
head -> next = nullptr;
return tmp;
}
};
12 剑指 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:
void dfs(TreeNode* &root) {
if (!root || (root -> left == nullptr && root -> right == nullptr)) {
return;
}
TreeNode* tmp = root -> left;
root -> left = root -> right;
root -> right = tmp;
dfs(root -> left);
dfs(root -> right);
}
TreeNode* mirrorTree(TreeNode* root) {
dfs(root);
return root;
}
};
13 剑指 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 dfs(TreeNode* node1, TreeNode* node2) {
if (node1 == nullptr && node2 == nullptr) {
return true;
}
if (node1 == nullptr || node2 == nullptr) {
return false;
}
if (node1 -> val != node2 -> val) {
return false;
}
return dfs(node1 -> left, node2 -> right) && dfs(node1 -> right, node2 -> left);
}
bool isSymmetric(TreeNode* root) {
if (!root) {
return true;
}
return dfs(root -> left, root -> right);
}
};
14 剑指 Offer 30. 包含min函数的栈 力扣
class MinStack {
public:
/** initialize your data structure here. */
stack res;
stack store;
MinStack() {
}
void push(int x) {
res.push(x);
if (store.empty() || store.top() > x) {
store.push(x);
} else {
store.push(store.top());
}
}
void pop() {
res.pop();
store.pop();
}
int top() {
return res.top();
}
int min() {
return store.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();
*/
15 剑指 Offer 31. 栈的压入、弹出序列 力扣
class Solution {
public:
bool validateStackSequences(vector& pushed, vector& popped) {
int size1 = pushed.size();
int size2 = popped.size();
stack sta;
if (size1 != size2) {
return false;
}
if (size1 == 0 && size2 == 0) {
return true;
}
int i = 0;
int j = 0;
for (; i < size1; ++i) {
sta.push(pushed[i]);
while(sta.size() != 0 && sta.top() == popped[j]) {
sta.pop();
j++;
}
}
return sta.empty();
}
};
16
剑指 Offer 34. 二叉树中和为某一值的路径 力扣
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void dfs(TreeNode* root, int sum, int target, vector vec, vector>& res) {
if (!root) {
return;
}
sum += root -> val;
vec.push_back(root -> val);
if (target == sum && root -> left == nullptr && root -> right == nullptr) {
res.push_back(vec);
}
dfs(root -> left, sum, target, vec, res);
dfs(root -> right, sum, target, vec, res);
vec.pop_back();
sum -= root -> val;
}
vector> pathSum(TreeNode* root, int target) {
int sum = 0;
vector> res;
vector vec;
dfs(root, sum, target, vec, res);
return res;
}
};
17 剑指 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* cur = head;
unordered_map map;
// 3. 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射
while(cur != nullptr) {
map[cur] = new Node(cur->val);
cur = cur->next;
}
cur = head;
// 4. 构建新链表的 next 和 random 指向
while(cur != nullptr) {
map[cur]->next = map[cur->next];
map[cur]->random = map[cur->random];
cur = cur->next;
}
// 5. 返回新链表的头节点
return map[head];
}
};
18 剑指 Offer 38. 字符串的排列 力扣
(1)set去重
class Solution {
public:
void dfs(string s, int i, int len, set& mySet, string tmpStr, vector& visit) {
if (i == len) {
mySet.insert(tmpStr);
return;
}
for(int j = 0; j < len; ++j) {
if (visit[j] == false) {
tmpStr += s[j];
visit[j] = true;
dfs(s, i + 1, len, mySet, tmpStr, visit);
visit[j] = false;
tmpStr.pop_back();
}
}
}
vector permutation(string s) {
set mySet;
string tmpStr;
int len = s.size();
vector visit(len, false);
vector res;
dfs(s, 0, len, mySet, tmpStr, visit);
set::iterator iter = mySet.begin();
for(; iter != mySet.end(); ++iter) {
res.push_back(*iter);
}
return res;
}
};
19 剑指 Offer 40. 最小的k个数 力扣
class Solution {
public:
vector getLeastNumbers(vector& arr, int k) {
priority_queue, less> buffer;
vector res;
int len = arr.size();
if (len == 0 || k == 0) {
return res;
}
for(int i = 0; i < len; ++i) {
if (i < k) {
buffer.push(arr[i]);
} else {
if (arr[i] < buffer.top()) {
buffer.pop();
buffer.push(arr[i]);
}
}
}
while(buffer.size()!= 0) {
res.push_back(buffer.top());
buffer.pop();
}
return res;
}
};
20 剑指 Offer 45. 把数组排成最小的数 力扣
class Solution {
public:
string minNumber(vector& nums) {
vector strs;
string res;
for(auto num:nums)
strs.push_back(to_string(num));
sort(strs.begin(),strs.end(),compare);
for(auto str:strs)
res+=str;
return res;
}
private:
static bool compare(const string &a,const string &b)
{
return a+b
21 剑指 Offer 47. 礼物的最大价值 力扣
class Solution {
public:
int maxValue(vector>& grid) {
int rows = grid.size();
if (rows == 0) {
return 0;
}
int cols = grid[0].size();
vector> vec(rows, vector(cols, 0));
vec[0][0] = grid[0][0];
for(int i = 1; i < rows; ++i) {
vec[i][0] = vec[i - 1][0] + grid[i][0];
}
for(int i = 1; i < cols; ++i) {
vec[0][i] = vec[0][i - 1] + grid[0][i];
}
for(int i = 1; i < rows; ++i) {
for(int j = 1; j < cols; ++j) {
vec[i][j] = grid[i][j] + max(vec[i - 1][j], vec[i][j - 1]);
}
}
return vec[rows - 1][cols - 1];
}
};
22 剑指 Offer 48. 最长不含重复字符的子字符串 力扣
class Solution {
public:
int lengthOfLongestSubstring(string s) {
/* 滑动窗口
int len = s.size();
if (len == 0 || len == 1) {
return len;
}
int left = 0, right = left + 1;
unordered_set mySet;
int resLen = 1;
int tmplen = 1;
mySet.insert(s[left]);
while(right < len) {
while(left < right && mySet.find(s[right]) != mySet.end()) {
mySet.erase(s[left]);
left++;
}
mySet.insert(s[right]);
resLen = max(resLen, right - left + 1);
right++;
}
return resLen; */
/* 动态规划 */
int size = s.size();
if (size == 0 || size == 1) {
return size;
}
map myMap;
vector dp(size, -1);
dp[0] = 1;
for(int i = 0; i < size; ++i) {
myMap[s[i]] = -1;
}
myMap[s[0]] = 0;
for(int i = 1; i < size; ++i) {
if (i - myMap[s[i]] > dp[i - 1]) {
dp[i] = dp[i - 1] + 1;
} else {
dp[i] = i - myMap[s[i]];
}
myMap[s[i]] = i;
}
int max = -1;
for(int i = 0; i < size; ++i) {
if (dp[i] > max) {
max = dp[i];
}
}
return max;
}
};
23 剑指 Offer 54. 二叉搜索树的第k大节点 力扣
/**
* 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:
void dfs(TreeNode* root, vector& vec) {
if (!root) {
return;
}
dfs(root -> left, vec);
vec.push_back(root -> val);
dfs(root -> right, vec);
}
int kthLargest(TreeNode* root, int k) {
if (!root) {
return 0;
}
vector vec;
dfs(root, vec);
int index = vec.size() - k;
return vec[index];
}
};
24 剑指 Offer 61. 扑克牌中的顺子 力扣
class Solution {
public:
bool isStraight(vector& nums) {
sort(nums.begin(), nums.end());
int count = 0;
int wang = 0;
for(int i = 0; i < 4; ++i) {
if (nums[i] == 0) {
wang++;
}
if (nums[i] == nums[i+ 1] && nums[i] != 0) {
return false;
}
if (nums[i + 1] > nums[i] && nums[i] != 0) {
count += (nums[i + 1] - nums[i] - 1);
}
}
if (wang >= count) {
return true;
}
return false;
}
};
25 剑指 Offer 63. 股票的最大利润 剑指 Offer 63. 股票的最大利润 - 力扣(LeetCode) (leetcode-cn.com)
class Solution {
public:
int maxProfit(vector& prices) {
//如果prices[i]大于min,则去更新一下利润res
//否则说明当前的prices[i]比min还小,则更新min
int size = prices.size();
if (size == 0) {
return 0;
}
int min = prices[0];
int optimum = 0;
for (int i = 1; i < size; ++i) {
if (prices[i] <= min) {
min = prices[i];
} else if (prices[i] > min) {
optimum = max(prices[i] - min, optimum);
}
}
return optimum;
}
};
26 剑指 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> levelOrder(TreeNode* root) {
vector> res;
if (!root) {
return res;
}
queue qu;
vector tmpVec;
qu.push(root);
bool flag = false;
while(!qu.empty()) {
int size = qu.size();
for (int i = 0; i < size; ++i) {
TreeNode* tmpNode = qu.front();
qu.pop();
tmpVec.push_back(tmpNode -> val);
if (tmpNode -> left) {
qu.push(tmpNode -> left);
}
if (tmpNode -> right) {
qu.push(tmpNode -> right);
}
}
flag = !flag;
if (flag == true) {
res.push_back(tmpVec);
} else {
reverse(tmpVec.begin(), tmpVec.end());
res.push_back(tmpVec);
}
tmpVec.clear();
}
return res;
}
};
27 剑指 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> levelOrder(TreeNode* root) {
vector> res;
if (!root) {
return res;
}
queue qu;
vector tmpVec;
qu.push(root);
bool flag = false;
while(!qu.empty()) {
int size = qu.size();
for (int i = 0; i < size; ++i) {
TreeNode* tmpNode = qu.front();
qu.pop();
tmpVec.push_back(tmpNode -> val);
if (tmpNode -> left) {
qu.push(tmpNode -> left);
}
if (tmpNode -> right) {
qu.push(tmpNode -> right);
}
}
flag = !flag;
if (flag == true) {
res.push_back(tmpVec);
} else {
reverse(tmpVec.begin(), tmpVec.end());
res.push_back(tmpVec);
}
tmpVec.clear();
}
return res;
}
};
28 剑指 Offer 56 - I. 数组中数字出现的次数 力扣
看下这两个帖子基础知识 https://blog.csdn.net/qq_19018277/article/details/103812534?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.essearch_pc_relevant
leetcode算法总结 —— 位运算_Charles Ren's Tech Blog-CSDN博客
class Solution {
public:
vector singleNumbers(vector& nums) {
int two = 2;
int size = nums.size();
vector part1;
vector part2;
vector res;
int x = 0;
for (int i = 0; i < size; ++i) {
x = x ^ nums[i];
}
//从右向左找第一个1,记录这个1的位置,说明两个单数该位不同,再依据这位不同将数组分成两组,则两个单数一定分别在两组,两组各自抑或,找到各自的单数
// 获取一个数二进制最低位的1
int y = x & (-x);
for (int i = 0; i < size; ++i) {
int w = nums[i] & y;
if (w == y) {
part1.push_back(nums[i]);
} else {
part2.push_back(nums[i]);
}
}
int z = 0;
for (int i = 0; i < part1.size(); ++i) {
z= z^ part1[i];
}
res.push_back(z);
int m = 0;
for (int i = 0; i < part2.size(); ++i) {
m= m^ part2[i];
}
res.push_back(m);
return res;
}
};
29 剑指 Offer II 073. 狒狒吃香蕉 力扣
class Solution {
public:
int times(int index, int speed, vector& piles) {
if (piles[index] % speed != 0) {
return piles[index] / speed + 1;
} else {
return piles[index] / speed;
}
}
int minEatingSpeed(vector& piles, int h) {
sort(piles.begin(), piles.end());
int size = piles.size();
int right = piles[size - 1];
double sum = 0;
int left = 1;
int res = right;
while (left <= right) {
int mid = (left + right) / 2;
int tmpsum = 0;
for (int i = 0; i < size; ++i) {
tmpsum += times(i, mid, piles);
}
if (tmpsum > h) {
left = mid + 1;
} else {
if (mid < res) {
res = mid;
}
right = mid - 1;
}
}
return res;
}
};
30 剑指 Offer 56 - II. 数组中数字出现的次数 II 力扣
class Solution {
public:
int singleNumber(vector& nums) {
/* 如果把所有的出现三次的数字的二进制表示的每一位都分别加起来,那么每一位都能被3整除。 我们把数组中所有的数字的二进制表示的每一位都加起来。如果某一位能被3整除,那么这一位对只出现一次的那个数的这一肯定为0。如果某一位不能被3整除,那么只出现一次的那个数字的该位置一定为1. */
vector vec(32, 0);
int sum = 0;
int size = nums.size();
for (int i = 0; i < size; ++i) {
for (int j = 0; j < 32; ++j) {
vec[j] += nums[i] & 1;
nums[i] = (nums[i] >> 1);
}
}
for (int i = 0; i < 32; ++i) {
if (vec[i] % 3 == 1) {
sum += pow(2, i);
}
}
return sum;
}
}
31 剑指 Offer 57 - II. 和为s的连续正数序列 力扣
class Solution {
public:
vector> findContinuousSequence(int target) {
vector> res;
if (target == 1) {
return res;
}
int left = 1, right = left + 1;
vector tmpvec;
while (right <= target / 2 + 1 && left <= right) {
int tmpSum = 0;
for (int i = left; i <= right; i ++) {
tmpSum += i;
}
if (tmpSum < target) {
right++;
tmpSum += right;
}
else if (tmpSum > target) {
left++;
tmpSum -= left;
}
else if (tmpSum == target) {
for (int m = left; m <= right; ++m) {
tmpvec.push_back(m);
}
res.push_back(tmpvec);
tmpvec.clear();
left++;
right++;
}
}
return res;
}
};
32 剑指 Offer 58 - I. 翻转单词顺序 力扣
class Solution {
public:
string reverseWords(string s) {
stack sta;
int len = s.length();
if (len == 0) {
return s;
}
int i = 0;
string tmpstr = "";
while (i < len) {
while (i < len && s[i] == ' ') {
++i;
}
while (i < len && s[i] != ' ') {
tmpstr += s[i];
++i;
}
sta.push(tmpstr);
tmpstr = "";
}
string res;
while(!sta.empty()) {
res += sta.top();
sta.pop();
res += " ";
int l = res.size();
if (sta.empty()) {
if (res[l - 1] == ' ') {
res = res.substr(0, l - 1);
}
}
}
int j = 0;
int x = res.size();
while (j < x && res[j] == ' ') {
j++;
}
return res.substr(j, x - j);
}
};
33 剑指 Offer 59 - II. 队列的最大值 力扣
class MaxQueue {
public:
queue qu;
deque deq;
MaxQueue() {
}
int max_value() {
if (qu.empty() || deq.empty()) {
return -1;
}
return deq.front();
}
void push_back(int value) {
qu.push(value);
while (!deq.empty() && value > deq.back()) {
deq.pop_back();
}
deq.push_back(value);
}
int pop_front() {
if (qu.empty()) {
return -1;
}
int tmp = qu.front();
qu.pop();
if (!deq.empty() && deq.front() == tmp) {
deq.pop_front();
}
return tmp;
}
};
34 剑指 Offer II 002. 二进制加法 力扣
class Solution {
public:
string addBinary(string a, string b) {
int lena = a.size();
int lenb = b.size();
int carry = 0;
string res = "";
if (lena > lenb) {
string tmp = string(lena - lenb, '0');
tmp += b;
b = tmp;
} else if (lena < lenb) {
string tmp = string(lenb - lena, '0');
tmp += a;
a = tmp;
}
int cur = b.size() - 1;
while (cur >= 0) {
if ((a[cur] - '0') + (b[cur] - '0') + carry == 0) {
res += "0";
carry = 0;
}
else if ((a[cur] - '0') + (b[cur] - '0') + carry == 1) {
res += "1";
carry = 0;
}
else if ((a[cur] - '0') + (b[cur] - '0') + carry == 2) {
res += "0";
carry = 1;
}
else if ((a[cur] - '0') + (b[cur] - '0') + carry == 3) {
res += "1";
carry = 1;
}
cur--;
}
if (carry == 1) {
res += "1";
}
reverse(res.begin(), res.end());
return res;
}
};
35 剑指 Offer II 003. 前 n 个数字二进制中 1 的个数
力扣
class Solution {
public:
vector countBits(int n) {
/* 动态规划: 使用dp[i]记录i中1的个数; 如果i是奇数,二进制1的个数等于dp[i-1] + 1; 如果i是偶数,相当于(i / 2)左移一位,1的个数和i/2相等。 */
vector dp(n + 1, 0);
dp[0] = 0;
for (int i = 1; i <= n; ++i) {
if (i % 2 == 1) {
dp[i] = dp[i - 1] + 1;
} else {
dp[i] = dp[i / 2];
}
}
return dp;
}
};
36 剑指 Offer II 005. 单词长度的最大乘积
class Solution {
public:
int maxProduct(vector& words) {
int size = words.size();
vector tmp(26, 0);//num为向量行数,0为初始化值
vector> vec(size, tmp);
for (int i = 0; i < size; ++i) {
for (int j = 0; j < words[i].size(); ++j) {
vec[i][words[i][j] - 'a']++;
}
}
int ret = 0;
int k, i, j;
for (i = 0; i < size; ++i) {
for (j = i + 1; j < size; ++j) {
for (k = 0; k < 26; ++k) {
if (vec[i][k] != 0 && vec[j][k] != 0) {
break;
}
}
if (k == 26) {
if (words[i].size() * words[j].size() > ret) {
ret = words[i].size() * words[j].size();
}
}
}
}
return ret;
}
};
37 剑指 Offer II 007. 数组中和为 0 的三个数 力扣
class Solution {
public:
vector> threeSum(vector& nums) {
int len = nums.size();
set> res;
sort(nums.begin(), nums.end());
int i = 0;
for(; i < len-2; i++) {
int j = i;
if (nums[i] > 0) {
break;
}
while(nums[i] == nums[i+1] && i < len-2)
i++;
int num = nums[j];
int target = -num;
int l = j+1, r = len-1;
while(l < r) {
int temp = nums[l] + nums[r];
if(temp == target) {
res.insert({num, nums[l], nums[r]});
while(l + 1 < len && nums[l] == nums[l + 1]) {
l++;
}
while(r > l && nums[r] == nums[r-1]) {
r--;
}
l++,r--;
} else if(temp > target) {
r--;
} else {
l++;
}
}
}
vector> ans;
ans.assign(res.begin(), res.end());
return ans;
}
};
38 剑指 Offer II 009. 乘积小于 K 的子数组
力扣
class Solution {
public:
int numSubarrayProductLessThanK(vector& nums, int k) {
// 当 k = 0 直接返回 0 即可
if(k == 0) return 0;
int count = 0; // 记录乘积小于 k 的连续的子数组的个数。
int product = 1; // 当前窗口内的数的乘积
int left = 0; // 窗口左边界
for(int right = 0; right < nums.size(); right++){
product *= nums[right];
// 当 窗口内数的乘积 >= k ,将窗口左边界向右移,同时更新窗口内数乘积
while (left <= right && product >= k){
product /= nums[left++];
}
// 统计该窗口中乘积小于 k 的连续的子数组的个数。
count += (right - left + 1);
}
return count;
}
};
39 剑指 Offer II 010. 和为 k 的子数组
力扣
class Solution {
public:
int subarraySum(vector& nums, int k) {
/* vector sum(nums.size() + 1);
for (int i = 0; i < nums.size(); ++i) {
sum[i + 1] = sum[i] + nums[i];
}
int ret = 0;
for (int i = 0; i < nums.size(); ++i) {
for (int j = 0; j <= i; ++j) {
if (sum[i + 1] - sum[j] == k) {
ret++;
}
}
}
return ret; */
//前缀和+hashmap组合
//用于存前缀和的个数
unordered_map mp;
int sum = 0;
int res = 0;
mp[0] = 1;
for(int i=0; i
40 剑指 Offer II 011. 0 和 1 个数相同的子数组
力扣
class Solution {
public:
/*
剑指 Offer II 010. 和为 k 的子数组
和这道题做法一样,如果这道题把0看成-1 做法就完全一样 */
int findMaxLength(vector& nums) {
int size = nums.size();
unordered_map mymap;
int sum = 0;
int ret = 0;
int x = -1;
for (int i = 0; i < size; ++i) {
if (nums[i] == 0) {
sum += x;
} else {
sum += 1;
}
if (sum == 0 && ret < i + 1) {
ret = i + 1;
}
if (mymap.find(sum) == mymap.end()) {
mymap[sum] = i;
} else {
if (ret < i - mymap[sum]) {
ret = i - mymap[sum];
}
}
}
return ret;
}
};
41 剑指 Offer II 013. 二维子矩阵的和 力扣
class NumMatrix {
public:
vector> vec;
NumMatrix(vector>& matrix) {
int rows = matrix.size();
int cols = matrix[0].size();
vec.resize(rows + 1, vector(cols + 1, 0)); // rows和cols都加一是为了在sumRegion里少if,否则可以看下注释里if很多
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
vec[i + 1][j + 1] = vec[i + 1][j] - vec[i][j] + matrix[i][j] + vec[i][j + 1];
}
}
}
int sumRegion(int row1, int col1, int row2, int col2) {
//if (row1 > 0 && col1 > 0) {
return vec[row2 + 1][col2 + 1] - vec[row1][col2 + 1] - vec[row2 + 1][col1] + vec[row1][col1];
//return vec[row2][col2] - vec[row1 - 1][col2] - vec[row2][col1 - 1] + vec[row1 - 1][col1 - 1];
/* } else if (row1 == 0 && col1 == 0) {
return vec[0][0];
}else if (col1 == 0) {
return vec[row2][col2] - vec[row1-1][col2];
} else if (row1 == 0) {
return vec[row2][col2] - vec[row2][col1 - 1];
}
return -1; */
}
};
42 剑指 Offer II 012. 左右两边子数组的和相等
力扣
class Solution {
public:
int pivotIndex(vector& nums)
{
int len = nums.size();
vector sums(len+1);
for(int i = 1;i <= len;++i)
{
sums[i] = sums[i-1] + nums[i-1];
}
for(int i = 0;i < len;++i)
{
if(sums[i] == (sums[len] - sums[i+1])) return i;
}
return -1;
}
};
43 剑指 Offer II 041. 滑动窗口的平均值
力扣
class MovingAverage {
public:
/** Initialize your data structure here. */
double len;
deque deq;
double sum;
MovingAverage(int size) {
len = size;
}
double next(int val) {
if (deq.size() < len) {
deq.push_back(val);
sum += val;
return sum / deq.size();
} else {
int top = deq.front();
deq.pop_front();
sum -= top;
deq.push_back(val);
sum += val;
return sum / deq.size();
}
return 0.0;
}
};
/**
* Your MovingAverage object will be instantiated and called as such:
* MovingAverage* obj = new MovingAverage(size);
* double param_1 = obj->next(val);
*/
44 剑指 Offer II 016. 不含重复字符的最长子字符串 力扣
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int size = s.size();
int left = 0;
int right = 0;
unordered_map mp;
int len = 0;
int ret = 0;
for (int i = 0; i < size; ++i) {
mp[s[i]]++;
while (left <= i && mp[s[i]] > 1) {
mp[s[left]]--;
left++;
}
ret = max (ret, i - left + 1);
}
return ret;
}
};
45 剑指 Offer II 018. 有效的回文 力扣剑指 Offer II 018. 有效的回文
class Solution {
public:
bool isPalindrome(string s) {
int i = 0;
int j = s.size() - 1;
while (i < j) {
if (!isalnum(s[i])) {
i++;
}
else if (!isalnum(s[j])) {
j--;
}
else {
if (tolower(s[i]) != tolower(s[j])) {
return false;
}
else {
i++;
j--;
}
}
}
return true;
}
};
/* isalpha :判断一个字符是否为字母,如果是则返回true,否则返回false;
isdigit : 判断一个字符是否表示数字,如果是则返回true,否则返回false;
isalnum : 判断一个字符是否表示数字或者字母,如果是则返回true,否则返回false;
islower : 判断一个字符是否为小写字母,如果是则返回true,否则返回false;
isupper : 判断一个字符是否为大写字母,如果是则返回true,否则返回false;
tolower : 若字符为字母则转化为小写字母;
toupper : 若字符为字母则转化为大写字母;
46 剑指 Offer II 021. 删除链表的倒数第 n 个结点
力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0, head);
//引入虚假头结点真的就是非常好用
ListNode* fast = head;
ListNode* slow = dummy;
for (int i = 0; i < n; ++i) {
fast = fast->next;
}
while (fast) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
ListNode* ans = dummy->next;
delete dummy;
return ans;
}
};
47剑指 Offer II 022. 链表中环的入口节点
力扣
力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
/* // 可用map统计,看某一个节点是否被指向过
if(head==NULL) return NULL;
unordered_map my_map;
ListNode* tmp = head;
while(tmp!=NULL) {
if(my_map.find(tmp)==my_map.end()) {
my_map[tmp] = 1;
tmp = tmp->next;
}
else {
return tmp;
}
}
return NULL; */
/*
假设链表全长为 m+n,其中 m 表示环入口之前的长度,n 表示环的长度 当两指针第一次相遇,这时候快指针一定已经饶了环一圈了,我们假设相遇的位置距离环入口k,此时有下列状态: distance(fast) = m + n + k distance(slow) = m + k m + n + k = 2m + 2k ==> n = m + k ==> m = n - k 然后我们将快指针设回头节点,两根指针这时候同时按照步长为1前进,那么当慢指针走到环入口时,有以下状态: distance(fast) = distance(slow) = n - k 不难发现此时快指针也刚好走到环入口 */
/*
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head, *slow = head;
while (true) {
if (fast == nullptr || fast->next == nullptr) return nullptr;
fast = fast->next->next;
slow = slow->next;
if (fast == slow) break;
}
fast = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return fast;
}
};
作者:jyd
链接:https://leetcode-cn.com/problems/c32eOV/solution/jian-zhi-offer-ii-022-lian-biao-zhong-hu-8f1m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
}
};
48 剑指 Offer II 024. 反转链表
力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
/*
if (head == nullptr|| head -> next == nullptr) {
return head;
}
stack st;
ListNode* cur = head;
while(cur) {
st.push(cur);
cur = cur -> next;
}
ListNode* ret = st.top();
ListNode* res = st.top();
st.pop();
while (!st.empty()) {
ret -> next = st.top();
ret = ret -> next;
st.pop();
}
ret -> next = nullptr;
return res; */
// 调用递推公式反转当前结点之后的所有节点
// 返回的结果是反转后的链表的头结点
/*
if (head == nullptr || head -> next == nullptr) {
return head;
}
ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return newHead;
*/
if (head == nullptr || head -> next == nullptr) {
return head;
}
ListNode* pre = nullptr;
ListNode* now = head;
ListNode* after;
while (now) {
after = now -> next;
now -> next = pre;
pre = now;
now = after;
}
return pre;
}
};
49 剑指 Offer II 026. 重排链表
力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseLi(ListNode* head) {
if (head == nullptr || head -> next == nullptr) {
return head;
}
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* tmp_next = nullptr;
while(cur) {
tmp_next = cur -> next;
cur -> next = pre;
pre = cur;
cur = tmp_next;
}
return pre;
}
void reorderList(ListNode* head) {
int lenhead = 0;
ListNode* cur1 = head;
while (cur1) {
cur1 = cur1 -> next;
lenhead++;
}
int tag;
if (lenhead % 2== 1) {
tag = lenhead / 2 + 1;
} else{
tag = lenhead / 2;
}
ListNode* taga = head;
while (tag > 0) {
taga =taga-> next;
tag--;
}
ListNode* pre = head;
while (pre -> next != taga) {
pre = pre -> next;
}
pre -> next = nullptr;
ListNode* rever = reverseLi(taga);
ListNode* h1 = head;
ListNode* h2 = rever;
while (h1 && h2) {
ListNode* tmp1 = h1 -> next;
ListNode* tmp2 = h2 -> next;
h1 -> next = h2;
h2 -> next= tmp1;
h1 = tmp1;
h2 = tmp2;
}
}
};
50 剑指 Offer II 027. 回文链表
力扣
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
/* if (head == nullptr || head -> next == nullptr) {
return head;
}
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* tmp_next = nullptr;
while(cur) {
tmp_next = cur -> next;
cur -> next = pre;
pre = cur;
cur = tmp_next;
}
return pre; */
if (head == nullptr || head -> next == nullptr) {
return head;
}
ListNode* tmp = reverseList(head -> next);
head -> next -> next = head;
head -> next = nullptr;
return tmp;
}
bool isPalindrome(ListNode* head) {
if (head -> next == nullptr || head == nullptr) {
return true;
}
int len = 0;
ListNode* cur = head;
while(cur) {
len++;
cur = cur -> next;
}
ListNode* cur2 = head;
int dis = len / 2;
if (len % 2 == 1) {
while (dis >= 0) {
cur2 = cur2 -> next;
dis--;
}
} else {
while (dis >= 1){
cur2 = cur2 -> next;
dis--;
}
}
ListNode* cur3 = reverseList(cur2);
ListNode* cur5 = head;
int i = 1;
while (i <= len / 2) {
if (cur3 -> val != cur5 -> val) {
return false;
}
cur5 = cur5 -> next;
cur3 = cur3 -> next;
i++;
}
return true;
}
};
51 剑指 Offer II 028. 展平多级双向链表
力扣
/*
// Definition for a Node.
class Node {
public:
int val;
Node* prev;
Node* next;
Node* child;
};
*/
class Solution {
public:
vector vec;
void dfs(Node* head) {
if (!head) {
return;
}
vec.push_back(head);
dfs(head -> child);
dfs(head -> next);
}
Node* flatten(Node* head) {
if (!head) {
return head;
}
dfs(head);
Node* pree = nullptr;
for (int i = 0; i < vec.size() - 1; ++i) {
cout << vec[i] -> val;
vec[i + 1]->prev = vec[i];
vec[i] -> next = vec[i + 1];
vec[i] -> child = nullptr;
}
return vec[0];
}
};
52 剑指 Offer II 030. 插入、删除和随机访问都是 O(1) 的容器
力扣
生产随机数 如何在C++中产生随机数 - Eventide - 博客园
class RandomizedSet {
public:
map mymap;
vector vec;
RandomizedSet() {
}
bool insert(int val) {
if (mymap.count(val) != 0) {
return false;
}
vec.push_back(val);
mymap[val] = vec.size() - 1;
return true;
}
bool remove(int val) {
if (mymap.count(val) == 0) {
return false;
}
int loc = mymap[val];
vec[loc] = vec[vec.size() - 1];
mymap[vec[vec.size() - 1]] = loc;
vec.pop_back();
mymap.erase(val);
return true;
}
int getRandom() {
return vec[rand() % vec.size()];
}
};
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
53 剑指 Offer II 076. 数组中的第 k 大的数字 剑指 Offer II 076. 数组中的第 k 大的数字 - 力扣(LeetCode) (leetcode-cn.com)
class Solution {
public:
// less top是最大
// greater top是最大
// pair以及优先队列中用pair https://blog.csdn.net/hnjzsyjyj/article/details/108929993
int findKthLargest(vector& nums, int k) {
priority_queue, greater> vec; // top是最小的
int size = nums.size();
for (int i = 0; i < size; ++i) {
if (i < k) {
vec.push(nums[i]);
} else {
if (vec.top() < nums[i]) {
vec.pop();
vec.push(nums[i]);
}
}
}
return vec.top();
}
};
/*
vector中的元素是pair,如何对vector进行排序,排序原则是pair的first或者second
#include
#include
#include
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
pair p;
vector> vec;
int cmp(paira, pairb){
if (a.first != b.first)return a.first>b.first;
else return a.second
#include
#include
using namespace std;
typedef struct example
{
int elem1;
int elem2;
}example;
/*这个comparison函数很重要.如果希望升序排序,就是"<",降序排列就是">"号,这样便于直观记忆.如果希望用elem2作为比较标准
就把elem1改为elem2,这样结构体就以elem2为比较标准排序了.*/
bool comparison(example a,example b){
return a.elem1>N;
vector array(N);
for(int i=0;i>array[i].elem1>>array[i].elem2;
}
sort(array.begin(),array.end(),comparison);
for(int i=0;i
54 剑指 Offer II 033. 变位词组
力扣
class Solution {
public:
vector> groupAnagrams(vector& strs) {
// 建立一个map,str排序后做key,做value,在map中能找到的key就放入map
vector vec;
map> mymap;
int size = strs.size();
vector> res;
for (int i = 0; i < size; ++i) {
string tmp = strs[i];
sort(strs[i].begin(), strs[i].end());
mymap[strs[i]].push_back(tmp);
}
map>::iterator iter = mymap.begin();
for (; iter != mymap.end(); ++iter) {
res.push_back(iter -> second);
}
return res;
}
};
55 剑指 Offer II 068. 查找插入位置
力扣
class Solution {
public:
int searchInsert(vector& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
}
};
56 剑指 Offer II 081. 允许重复选择元素的组合
力扣
class Solution {
public:
vector tmpVec;
vector> res;
int i = 0;
void dfs(int i, int target, int sum, vector& candidates) {
if (sum == target) {
res.push_back(tmpVec);
}
if (sum < target) {
for (; i < candidates.size(); ++i) {
tmpVec.push_back(candidates[i]);
sum += candidates[i];
dfs(i, target, sum, candidates);
tmpVec.pop_back();
sum -= candidates[i];
}
}
}
vector> combinationSum(vector& candidates, int target) {
dfs(0, target, 0, candidates);
return res;
}
};
57 剑指 Offer II 082. 含有重复元素集合的组合 力扣
class Solution {
public:
vector tmpVec;
vector> res;
int i = 0;
set> myset;
void dfs(int i, int target, int sum, vector& candidates) {
if (sum == target) {
res.push_back(tmpVec);
}
if (sum < target) {
for (; i < candidates.size(); ++i) {
tmpVec.push_back(candidates[i]);
sum += candidates[i];
dfs(i + 1, target, sum, candidates);
tmpVec.pop_back();
sum -= candidates[i];
}
}
}
vector> combinationSum2(vector& candidates, int target) {
dfs(0, target, 0, candidates);
for (int i = 0; i < res.size(); ++i) {
sort(res[i].begin(), res[i].end());
myset.insert(res[i]);
}
vector> res2;
set, int>::iterator iter = myset.begin();
for (; iter != myset.end(); ++iter) {
res2.push_back(*iter);
}
return res2;
}
};
58 剑指 Offer II 083. 没有重复元素集合的全排列
力扣
class Solution {
public:
vector> res;
vector tmp;
void dfs(vector& nums, vector& visit) {
if (tmp.size() == nums.size()) {
res.push_back(tmp);
//tmp.clear();
return;
}
for (int i = 0; i < nums.size(); ++i) {
if (visit[i] == 0) {
tmp.push_back(nums[i]);
visit[i] = 1;
dfs(nums, visit);
visit[i] = 0;
tmp.pop_back();
}
}
}
vector> permute(vector& nums) {
int size = nums.size();
vector visit(size, 0);
dfs(nums, visit);
return res;
}
};
59 剑指 Offer II 069. 山峰数组的顶部
力扣
class Solution {
public:
int peakIndexInMountainArray(vector& arr) {
int size = arr.size();
int left = 0;
int right = size - 1;
int mid;
int res;
while (left <= right) {
mid = (left + right) / 2;
if (arr[mid] < arr[mid + 1]) {
left = mid + 1;
}
if (arr[mid] > arr[mid + 1]) {
res = mid;
right = mid - 1;
}
}
return res;
}
};
60 剑指 Offer II 035. 最小时间差
力扣
class Solution {
public:
int StrToTIme(string str) {
string hour = str.substr(0, 2);
string minute = str.substr(3, 2);
int h = (hour[0] - '0') * 10 + (hour[1] - '0');
int m = (minute[0] - '0') * 10 + (minute[1] - '0');
return h * 60 + m;
}
int findMinDifference(vector& timePoints) {
vector minGrp;
int size = timePoints.size();
for (int i = 0; i < size; ++i) {
minGrp.push_back(StrToTIme(timePoints[i]));
}
sort(minGrp.begin(), minGrp.end());
int ret = INT_MAX, Size = minGrp.size();
for (int i = 0; i < Size - 1; ++i) {
if (minGrp[i + 1] - minGrp[i] < ret) {
ret = minGrp[i + 1] - minGrp[i];
}
}
if (1440 + minGrp[0] - minGrp[Size - 1] < ret) {
ret = 1440 + minGrp[0] - minGrp[Size - 1];
}
return ret;
}
};
61 剑指 Offer II 038. 每日温度
力扣
class Solution {
public:
vector dailyTemperatures(vector& temperatures) {
// 单调栈
// 第一个元素入栈,若下一个元素比栈顶元素大 则找到了比栈顶元素大的第一个元素,弹出栈顶元素并记录结果值,不断反复弹出 直到找到比当前元素大的栈顶元素,再把当前元素放入栈
// 栈中存的是下标
int size = temperatures.size();
vector res(size, 0);
stack sta;
for (int i = 0; i < size; ++i) {
if (i == 0) {
sta.push(0);
}
while(sta.size() != 0 && temperatures[i] > temperatures[sta.top()]) {
res[sta.top()] = i - sta.top();
sta.pop();
}
sta.push(i);
}
return res;
}
};
62 剑指 Offer II 036. 后缀表达式
力扣
class Solution {
public:
int evalRPN(vector& tokens) {
/* 栈中只保存操作数,操作符不需要保存在栈中
如果遇到的是一个操作数,则将其入栈;如果遇到的是一个操作符,则两个操作数出栈并执行相应的运算,然后计算结果入栈 */
stack sta;
int size = tokens.size();
for (int i = 0; i < size; ++i) {
if (tokens[i] != "+" && tokens[i] != "-" && tokens[i] != "*" && tokens[i] != "/") {
sta.push(stoi(tokens[i]));
} else {
int right = sta.top();
sta.pop();
int left = sta.top();
sta.pop();
int ret = 0;
if (tokens[i] == "+") {
ret = left + right;
}
if (tokens[i] == "-") {
ret = left - right;
}
if (tokens[i] == "*") {
ret = left * right;
}
if (tokens[i] == "/") {
ret = left / right;
cout << ret;
}
/* switch (tokens[i]) {
case "+":
ret = left + right;
break;
case "-":
ret = left - right;
break;
case "*":
ret = left * right;
break;
default:
ret = left / right;
} */
sta.push(ret);
}
}
return sta.top();
}
};
63 剑指 Offer II 037. 小行星碰撞
力扣
class Solution {
public:
vector asteroidCollision(vector& asteroids) {
stack sta;
int size = asteroids.size();
for (int i = 0; i < size; ++i) {
while (sta.size() > 0 && sta.top() > 0 && asteroids[i] < 0 && sta.top() < (-asteroids[i])) {
sta.pop();
}
if (sta.size() > 0 && sta.top() > 0 && asteroids[i] < 0 && sta.top() == (-asteroids[i])) {
sta.pop();
}
else if (sta.size() == 0 || asteroids[i] > 0 || sta.top() < 0) {
sta.push(asteroids[i]);
}
}
vector res;
while (sta.size() != 0) {
res.push_back(sta.top());
sta.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
64 剑指 Offer II 049. 从根节点到叶节点的路径数字之和
力扣
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int dfs(TreeNode* root, int path) {
if (!root) {
return 0;
}
path = path * 10 + root -> val;
if (root -> left == nullptr && root -> right == nullptr) {
return path;
}
return dfs(root -> left, path) + dfs(root -> right, path);
}
int sumNumbers(TreeNode* root) {
return dfs(root, 0);
}
};
65 剑指 Offer II 105. 岛屿的最大面积 力扣
class Solution {
public:
int dfs(vector>& grid, int rows, int cols, int row, int col) {
if (row < 0 || col < 0 || row >= rows || col >= cols || grid[row][col] == 0) {
return 0;
}
grid[row][col] = 0;
return 1 + dfs(grid, rows, cols, row + 1, col) + dfs(grid, rows, cols, row, col + 1) + dfs(grid, rows, cols, row - 1, col) + dfs(grid, rows, cols, row, col - 1);
}
int maxAreaOfIsland(vector>& grid) {
int rows = grid.size();
int cols = grid[0].size();
int tmpMax = -1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; ++j) {
int t = dfs(grid, rows, cols, i, j);
if (tmpMax < t) {
tmpMax = t;
}
}
}
return tmpMax;
}
};
66 剑指 Offer II 058. 日程表
力扣
class MyCalendar {
public:
vector > v = vector > (1000, vector(2, 0));
int top = 0;
MyCalendar() {
}
bool book(int start, int end) {
if (top == 0) {
v[0][0] = start;
v[0][1] = end;
top = 1;
return true;
}
for (int i = 0; i < top; ++i) {
if (!(start >= v[i][1] || end <= v[i][0])) {
return false;
}
}
v[top][0] = start;
v[top][1] = end;
top++;
return true;
}
};
/**
* Your MyCalendar object will be instantiated and called as such:
* MyCalendar* obj = new MyCalendar();
* bool param_1 = obj->book(start,end);
*/
67 剑指 Offer II 045. 二叉树最底层最左边的值
力扣
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector> res;
vector v;
queue qu;
int findBottomLeftValue(TreeNode* root) {
qu.push(root);
while(!qu.empty()) {
int size = qu.size();
for (int i = 0; i < size; ++i) {
TreeNode* tmp = qu.front();
v.push_back(tmp -> val);
qu.pop();
if (tmp -> left) {
qu.push(tmp -> left);
}
if (tmp -> right) {
qu.push(tmp -> right);
}
}
res.push_back(v);
v.clear();
}
int layers = res.size();
return res[layers - 1][0];
}
};
68 剑指 Offer II 089. 房屋偷盗
力扣
class Solution {
public:
int rob(vector& nums) {
int size = nums.size();
vector vec(size + 1, 0);
vector visit(size + 1, 0);
if (size == 1) {
return nums[0];
}
vec[0] = nums[0];
vec[1] = max(nums[0], nums[1]);
int sum = 0;
for (int i = 2; i < size; ++i) {
vec[i] = max(vec[i - 1], vec[i - 2] + nums[i]);
}
return vec[size -1];
}
};
/* https://leetcode-cn.com/problems/Gu0c2T/solution/jian-zhi-offer-2-mian-shi-ti-89-shu-zhon-86xo/ */
69 剑指 Offer II 099. 最小路径之和
力扣
class Solution {
public:
int minPathSum(vector>& grid) {
int size = grid.size();
vector> vec(size, vector(grid[0].size(), 0));
vec[0][0] = grid[0][0];
for (int i = 1; i< grid[0].size(); ++i) {
vec[0][i] = vec[0][i - 1] + grid[0][i];
}
for (int i = 1; i< grid.size(); ++i) {
vec[i][0] = vec[i - 1][0] + grid[i][0];
}
for (int i = 1; i < size; ++i) {
for (int j = 1; j < grid[0].size(); ++j) {
vec[i][j] = min(vec[i - 1][j], vec[i][j - 1]) + grid[i][j];
}
}
return vec[size - 1][grid[0].size() - 1];
}
};
70 剑指 Offer II 100. 三角形中最小路径之和
class Solution {
public:
int minimumTotal(vector>& triangle) {
int rows = triangle.size();
int cols = triangle[rows - 1].size();
vector> vec(rows, vector(cols, 0)) ;
vec[0][0] = triangle[0][0];
for (int i = 1; i < rows; ++i) {
vec[i][0] = vec[i - 1][0] + triangle[i][0];
}
for (int i = 1; i < rows; ++i) {
for (int j = 1; j < i + 1; ++j) {
vec[i][j] = min(vec[i - 1][j - 1], vec[i - 1][j]) + triangle[i][j];
}
vec[i][i] = vec[i - 1][i - 1] + triangle[i][i];
}
int res = INT_MAX;
for (int i = 0; i < cols; ++i) {
if (vec[rows - 1][i] < res) {
res = vec[rows - 1][i];
}
}
return res;
}
};
71 剑指 Offer II 101. 分割等和子集
力扣
/*
设 f(i, j) 表示能否从前 i 个物品(物品编号为 0 ~ i - 1)中选择若干物品放满容量为 j 的背包。对于 f(i, j) 存在两个选择,第一个选择是将标号为 i - 1 的物品放入背包,如果能从前 i - 1 个物品中选择若干物品放满容量为 j - nums[i - 1] 的背包(即 f(i - 1, j - nums[i - 1]) 为 true),那么 f(i, j) 为 true。另一个选择是不把标号为 i - 1 的物品放入背包,如果能从前 i - 1 个物品中选择若干物品放满容量为 j 的背包(即 f(i - 1, j) 为 true),那么 f(i, j) 为 true。即
当 j 等于 0 时,即背包容量为空,只要不选择物品就可以,所以 f(i, 0) 为 true。当 i 等于 0 时,即物品数量为 0,那么除了空背包都无法装满,所以当 j 大于 0 时,f(0, j) 为 fasle;
作者:master_xue
链接:https://leetcode-cn.com/problems/NUPfPr/solution/jian-zhi-offer-2-mian-shi-ti-101-shu-zho-mt8e/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
class Solution {
public:
bool canPartition(vector& nums) {
int sum = 0;
for (auto& n : nums) {
sum += n;
}
if (sum & 1 != 0) {
return false;
}
int target = sum >> 1;
vector> dp(nums.size() + 1, vector(target + 1, false));
dp[0][0] = true;
for (int i = 1; i <= nums.size(); ++i) {
for (int j = 0; j <= target; ++j) {
dp[i][j] = dp[i - 1][j];
if (!dp[i][j] && j >= nums[i - 1]) {
dp[i][j] = dp[i - 1][j - nums[i - 1]];
}
}
}
return dp[nums.size()][target];
}
};
72 剑指 Offer II 091. 粉刷房子
力扣
class Solution {
public:
int minCost(vector>& costs) {
int size = costs.size();
vector> vec(100, vector(3, 0));
vec[0][0] = costs[0][0];
vec[0][1] = costs[0][1];
vec[0][2] = costs[0][2];
for (int i = 1; i < size; ++i) {
vec[i][0] = min(vec[i - 1][1], vec[i - 1][2]) + costs[i][0];
vec[i][1] = min(vec[i - 1][0], vec[i - 1][2]) + costs[i][1];
vec[i][2] = min(vec[i - 1][0], vec[i - 1][1]) + costs[i][2];
}
int res = 99999;
for (int i = 0; i < 3; ++i) {
if (vec[size - 1][i] < res) {
res = vec[size - 1][i];
}
}
return res;
}
};
确定状态转换:
题目要求:相邻的两间房子不能涂相同的颜色,那只要我们当前要涂的颜色和前一间不同就好 (废话)
假设我们现在到了第3间房子,我们考虑一下涂那种颜色:
假设涂红色:所以前一家房子只能是蓝色或者绿色,从他们中选一个最便宜的吧!
那就是 dp[2][0] = Math.min(dp[1][1],dp[1][2])+costs[2][0]
蓝色和绿色同理,由此我们可以得到状态转换方程!
dp[i][0] = Math.min(dp[i-1][1],dp[i-1][2])+costs[i][0];
dp[i][1] = Math.min(dp[i-1][0],dp[i-1][2])+costs[i][1];
dp[i][2] = Math.min(dp[i-1][0],dp[i-1][1])+costs[i][2];
73 剑指 Offer II 095. 最长公共子序列
力扣
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int size1 = text1.size();
int size2 = text2.size();
vector> vec(size1 + 1, vector (size2 + 1, 0));
// vec[i][j] = vec[i - 1][j - 1] + 1, text1[i] == text[j]
// vec[i][j] - max(vec[ i - 1][j], vec[i][j - 1]), text1[i] != text[j]
for (int i = 0; i < size1; ++i) {
for (int j = 0; j < size2; ++j) {
if (text1[i] == text2[j]) {
vec[i + 1][j + 1] = vec[i][j] + 1;
} else {
vec[i + 1][j + 1] = max(vec[i][j + 1], vec[i + 1][j]);
}
}
}
return vec[size1][size2];
}
};
74 剑指 Offer II 102. 加减的目标值
力扣
class Solution {
public:
int res = 0;
void dfs(vector& nums, int index, int size, int sum, int target) {
if (index == size) {
if (sum == target) {
res++;
}
return;
}
dfs(nums, index + 1, size, sum - nums[index], target);
dfs(nums, index + 1, size, sum + nums[index], target);
}
int findTargetSumWays(vector& nums, int target) {
int size = nums.size();
dfs(nums, 0, size, 0, target);
return res;
}
};
75 剑指 Offer II 098. 路径的数目
力扣
class Solution {
public:
int uniquePaths(int m, int n) {
int rows = m - 1;
int cols = n - 1;
vector> vec(m, vector(n, 1));
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
vec[i][j] = vec[i - 1][j] + vec[i][j - 1];
}
}
return vec[m - 1][n - 1];
}
};
76 剑指 Offer II 053. 二叉搜索树中的中序后继
力扣
/**
* 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 vec;
void MidOrder(TreeNode* root) {
if (!root) {
return;
}
MidOrder(root -> left);
vec.push_back(root);
MidOrder(root -> right);
}
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
MidOrder(root);
int size = vec.size();
for (int i = 0; i < size; ++i) {
if (i != size -1 && p == vec[i]) {
return vec[i + 1];
}
}
return nullptr;
}
};
77 剑指 Offer II 075. 数组相对排序
力扣
class Solution {
public:
vector relativeSortArray(vector& arr1, vector& arr2) {
int size1 = arr1.size();
vector hash(size1, 0);
int size2 = arr2.size();
vector res;
for (int i = 0; i < size2; ++i) {
for (int j = 0; j < size1; ++j) {
if (arr2[i] == arr1[j] && hash[j] == 0) {
res.push_back(arr1[j]);
hash[j] = 1;
}
}
}
vector tmpVec;
for (int i = 0; i < size1; ++i) {
if (hash[i] == 0) {
tmpVec.push_back(arr1[i]);
}
}
sort(tmpVec.begin(), tmpVec.end());
for (int i = 0; i < tmpVec.size(); ++i) {
res.push_back(tmpVec[i]);
}
return res;
}
};
78 剑指 Offer II 052. 展平二叉搜索树 力扣
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector vec;
void MidOrder(TreeNode* root) {
if (!root) {
return;
}
MidOrder(root -> left);
vec.push_back(root -> val);
MidOrder(root -> right);
}
TreeNode* increasingBST(TreeNode* root) {
MidOrder(root);
int size = vec.size();
TreeNode* res = new TreeNode(0);
TreeNode* tmp = res;
for (int i = 0; i < size; ++i) {
TreeNode* node = new TreeNode(vec[i]);
node -> left = nullptr;
tmp -> right = node;
tmp = node;
}
return res -> right;
}
};
79 剑指 Offer II 110. 所有路径
力扣
class Solution {
public:
vector> res;
vector tmp;
void dfs(vector>& graph, int size, int index) {
if (index == size - 1) {
res.push_back(tmp);
}
for (int i = 0; i < graph[index].size(); ++i) {
tmp.push_back(graph[index][i]);
dfs(graph, size, graph[index][i]);
tmp.pop_back();
}
}
vector> allPathsSourceTarget(vector>& graph) {
int size = graph.size();
tmp.push_back(0);
dfs(graph, size, 0);
return res;
}
};
80 剑指 Offer II 059. 数据流的第 K 大数值
力扣
class KthLargest {
public:
int K;
priority_queue, greater> q; // top是最小的队列底是最大的,维持一个K大小的队列能把最大的K个数永远放对列
vector vec;
KthLargest(int k, vector& nums) {
K = k;
for (int i = 0; i < nums.size(); ++i) {
q.push(nums[i]);
}
}
int add(int val) {
q.push(val);
while(q.size() > K) {
q.pop();
}
return q.top();
}
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/