Leetcode
数组
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
数组
1. 两数之和
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res(2,-1);
unordered_map<int,int> hash;
for(int i=0;i<nums.size();i++)
{
if(hash.count(target - nums[i])!=0)
{
res[0] = i;
res[1] = hash[target - nums[i]];
break;
}
hash[nums[i]] = i;
}
return res;
}
26. 删除排序数组中的重复项
int removeDuplicates(vector<int>& nums) {
int n = nums.size();
if(!n) return 0;
int index =1;
for(int i=1;i<n;i++)
{
if(nums[i] != nums[i-1])
{
nums[index++] = nums[i];
}
}
while(nums.size()!=index)
{
nums.pop_back();
}
return index;
}
31. 下一个排列
/*
以排列 [4,5,2,6,3,1]为例:
我们能找到的符合条件的一对「较小数」与「较大数」的组合为 22 与 33,满足「较小数」尽量靠右,而「较大数」尽可能小。
当我们完成交换后排列变为 [4,5,3,6,2,1],此时我们可以重排「较小数」右边的序列,序列变为 [4,5,3,1,2,6]。
*/
void nextPermutation(vector<int>& nums) {
int n = nums.size();
int i = n -2;
while(i>=0 && nums[i] >= nums[i+1]){
i--;
}
if(i>=0){
int j = n -1;
while(j>=0 && nums[j] <= nums[i]){
j--;
}
swap(nums[i], nums[j]);
}
reverse(nums.begin() + i + 1, nums.end());
}
36. 有效的数独
bool isValidSudoku(vector<vector<char>>& board) {
int n = board.size();
if(!n) return true;
int m = board[0].size();
unordered_map<char, int> hash;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(board[i][j]!='.')
{
hash[board[i][j]]++;
if(hash[board[i][j]]>1)
{
return false;
}
}
}
hash.clear();
}
for(int j=0;j<m;j++)
{
for(int i=0;i<n;i++)
{
if(board[i][j]!='.')
{
hash[board[i][j]]++;
if(hash[board[i][j]]>1)
{
return false;
}
}
}
hash.clear();
}
for(int i=0;i<n;i+=3)
{
for(int j=0;j<m;j+=3)
{
for(int s = i;s<i+3;s++)
{
for(int k = j;k<j+3;k++)
{
if(board[s][k]!='.')
{
hash[board[s][k]]++;
if(hash[board[s][k]]>1)
{
return false;
}
}
}
}
hash.clear();
}
}
return true;
}
48. 旋转图像
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for(int i=0;i<n;i++)
{
for(int j = i;j<n;j++)
{
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
for(int i = 0;i<n;i++)
{
for(j = 0;j<n/2;j++)
{
int temp = matrix[i][j];
matrix[i][j] = matrix[i][n-j-1];
matrix[i][n-j-1] = temp;
}
}
return;
}
54. 螺旋矩阵
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int n = matrix.size();
if(!n) return res;
int m = matrix[0].size();
vector<vector<bool>> st(n,vector<bool>(m,false));
int x = 0;
int y = 0;
int dx[4] = {0,1,0,-1};//上下
int dy[4] = {1,0,-1,0};//左右
int d = 0;
for(int i=0;i<m*n;i++)
{
res.push_back(matrix[x][y]);
st[x][y] = true;
int a = x + dx[d];
int b = y + dy[d];
if(a>=n||a<0||b>=m||b<0||st[a][b])
{
d = (d+1)%4;
a = x + dx[d];
b = y + dy[d];
}
x = a;
y = b;
}
return res;
}
56. 合并区间
bool static cmp(vector<int>& a, vector<int>& b)
{
return a[0] < b[0];
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> res;
if(!intervals.size()) return res;
sort(intervals.begin(),intervals.end(),cmp);
res.push_back(intervals[0]);
for(int i=0;i<intervals.size();i++)
{
vector<int> temp = res.back();
int tail = temp[1];
if(tail<intervals[i][0])
{
res.push_back(intervals[i]);
}
else
{
res.back()[1] = max(intervals[i][1],tail);
}
}
return res;
}
73. 矩阵置零
void setZeroes(vector<vector<int>>& matrix) {
int n = matrix.size();
if(!n) return;
int m = matrix[0].size();
vector<bool> row(n,false), col(m, false);
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(matrix[i][j]==0)
{
row[i] = true;
col[j] = true;
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(row[i]==true)
{
matrix[i][j] = 0;
}
if(col[j] == true)
{
matrix[i][j] = 0;
}
}
}
return;
}
88. 合并两个有序数组
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int j = 0;
for(int i = m;i<m+n;i++)
{
nums1[i] = nums2[j++];
}
vector<int> vec(m+n);
int i = 0;
j = m;
int k = 0;
while(i<m&&j<(m+n))
{
vec[k++] = nums1[i] < nums1[j]? nums1[i++]:nums1[j++];
}
while(i<m)
{
vec[k++] = nums1[i++];
}
while(j<m+n)
{
vec[k++] = nums1[j++];
}
copy(vec.begin(),vec.end(), nums1.begin());
return;
}
118. 杨辉三角
vector<int> Transform(vector<int> nums)
{
vector<int> res;
res.push_back(1);
for(int i=1;i<nums.size();i++)
{
res.push_back(nums[i] + nums[i-1]);
}
res.push_back(1);
return res;
}
vector<vector<int>> generate(int numRows) {
vector<vector<int>> res;
if(numRows==0) return res;
if(numRows==1)
{
res.push_back({1});
return res;
}
res.push_back({1});
for(int i=1;i<numRows;i++)
{
res.push_back(Transform(res[i-1]));
}
return res;
}
128. 最长连续序列
int longestConsecutive(vector<int>& nums) {
unordered_set<int> hash;
int res = 0;
for(auto num: nums){
hash.insert(num);
}
for(int i=0;i<nums.size();++i){
if(!hash.count(nums[i]-1)){
int current_num = nums[i];
int current_break = 1;
while(hash.count(current_num + 1)){
current_num +=1;
current_break +=1;
}
res = max(current_break, res);
}
}
return res;
}
238. 除自身以外数组的乘积
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> res(n,0);
if(!n) return res;
int p = 1;
for(int i=0;i<n;i++)
{
res[i] = p;
p = p*nums[i];
}
p = 1;
for(int i = n-1;i>=0;i--)
{
res[i] *= p;
p = p*nums[i];
}
return res;
}
240. 搜索二维矩阵 II
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int n = matrix.size();
if(!n) return false;
int m = matrix[0].size();
if(!m) return false;
int i = 0;
int j= m-1;
while(i<n && j>=0)
{
if(matrix[i][j]==target)
{
return true;
}
else if(matrix[i][j]>target)
{
j--;
}
else if(matrix[i][j]<target)
{
i++;
}
}
return false;
}
287. 寻找重复数
int findDuplicate(vector<int>& nums) {
int n = nums.size();
for(int i=0;i<n;i++)
{
while(nums[i] != i+1)
{
if(nums[nums[i]-1]==nums[i])
{
return nums[i];
}
else
{
swap(nums[i],nums[nums[i]-1]);
}
}
}
return -1;
}
349. 两个数组的交集
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
vector<int> res;
if(!nums1.size()||!nums2.size())
{
return res;
}
unordered_set<int> s;
for(auto num: nums1)
{
s.insert(num);
}
for(auto a: nums2)
{
if(s.count(a)>0)
{
res.push_back(a);
s.erase(a);
}
}
return res;
}
栈
20. 有效的括号
bool iscoff(char a, char b)
{
if(a == '('&& b == ')' )
{
return true;
}
else if(a == '{'&& b =='}')
{
return true;
}
else if(a == '['&& b == ']')
{
return true;
}
return false;
}
bool isValid(string s) {
stack<char> st;
for(auto a:s)
{
if(a=='('||a=='{'||a=='[')
{
st.push(a);
}
else if(a==')'||a=='}'||a==']')
{
if(st.empty())
{
return false;
}
char temp = st.top();
st.pop();
if(!iscoff(temp,a))
{
return false;
}
}
}
if(st.size())
{
return false;
}
return true;
}
滑动窗口
模板
void slidingWin(string str, string t)
{
unordered_map<int, int> hashmap, win;
for(char c : t) hashmap[c]++;
int valid = 0;
for(int l = 0, r = 0; r < str.size();)
{
//扩大窗口
char ch = str[r];
//窗口右移
r++;
//进行窗口内数据的一系列更新
...
cout << l << " " << r << endl;
// 窗口右移动
while() // 满足某个条件
{
//d是即将要移动出窗口的字符
char d = str[l];
//左移窗口
l++;
//更新结果
...
}
}
}
3. 无重复字符的最长子串
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> hashmap;
int cnt = 0;
for(int i = 0, j = 0; j < s.size(); j++)
{
hashmap[s[j]]++;
while(hashmap[s[j]] > 1) hashmap[s[i++]]--;
cnt = max(cnt, j - i + 1);
}
return cnt;
}
76. 最小覆盖子串
string minWindow(string s, string t) {
vector<int> need(128,0);
int count = 0;
for(char c : t)
{
need[c]++;
}
count = t.length();
int l=0, r=0, start=0, size = INT_MAX;
while(r<s.length())
{
char c = s[r];
if(need[c]>0)
count--;
need[c]--; //先把右边的字符加入窗口
if(count==0) //窗口中已经包含所需的全部字符
{
while(l<r && need[s[l]]<0) //缩减窗口
{
need[s[l++]]++;
} //此时窗口符合要求
if(r-l+1 < size) //更新答案
{
size = r-l+1;
start = l;
}
need[s[l]]++; //左边界右移之前需要释放need[s[l]]
l++;
count++;
}
r++;
}
return size==INT_MAX ? "" : s.substr(start, size);
239. 滑动窗口最大值
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(nums.empty()) return vector<int>();
deque<int> q;
vector<int> res;
for(int i=0;i<nums.size();i++)
{
while(q.size()&&q.front()+k<=i) q.pop_front();
while(q.size()&&nums[q.back()]<=nums[i]) q.pop_back();
q.push_back(i);
if(i>=k-1)
{
res.push_back(nums[q.front()]);
}
}
return res;
}
链表
2. 两数相加
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* dummy = new ListNode(0);
ListNode* cur = dummy;
ListNode* p = l1;
ListNode* q = l2;
int carry = 0;
while(p!=nullptr||q!=nullptr)
{
int s1 = p?p->val:0;
int s2 = q?q->val:0;
int sum = s1 + s2 + carry;
cur->next = new ListNode(sum%10);
cur = cur->next;
carry = sum/10;
if(p)
{
p = p->next;
}
if(q)
{
q = q->next;
}
}
if(carry!=0)
{
cur->next = new ListNode(carry);
}
return dummy->next;
}
21. 合并两个有序链表
非递归实现
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(!l1) return l2;
if(!l2) return l1;
ListNode* res;
if(l1->val<l2->val)
{
res = l1;
res->next = mergeTwoLists(l1->next,l2);
}
else
{
res = l2;
res->next = mergeTwoLists(l1,l2->next);
}
return res;
}
24. 两两交换链表中的节点
递归
ListNode* swapPairs(ListNode* head) {
if (head == nullptr || head->next == nullptr) {
return head;
}
ListNode* newHead = head->next;
head->next = swapPairs(newHead->next);
newHead->next = head;
return newHead;
}
非递归
ListNode* swapPairs(ListNode* head) {
if(!head || !head->next){
return head;
}
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* p = dummy;
while(p->next && p->next->next){
ListNode* node1 = p->next;
ListNode* node2 = p->next->next;
ListNode* next_node = node2->next;
p->next = node2;
node2->next = node1;
node1->next = next_node;
p = p->next->next;
}
return dummy->next;
}
25. K个一组反转链表
// 翻转一个子链表,并且返回新的头与尾
pair<ListNode*, ListNode*> reverse(ListNode* head, ListNode* tail){
ListNode* pre = tail->next;
ListNode* cur = head;
while(pre!=tail){
ListNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return {tail, head};
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* fake = new ListNode(-1);
fake->next = head;
ListNode* pre = fake;
while(head){
ListNode* tail = pre;
for(int i=0;i<k;i++){
tail = tail->next;
if(tail == nullptr){
return fake->next;
}
}
ListNode* nex = tail->next;
pair<ListNode*, ListNode*> node = reverse(head, tail);
node.second->next = nex;
pre->next = node.first;
pre = node.second;
head = node.second->next;
}
return fake->next;
}
82. 删除排序链表中的重复元素 II
ListNode* deleteDuplicates(ListNode* head) {
ListNode* fake = new ListNode(-1);
fake->next = head;
ListNode* p = fake;
while(p->next){
auto q = p->next;
while(q && q->val == p->next->val){
q = q->next;
}
if(p->next->next == q){
p = p->next;
} else {
p->next = q;
}
}
return fake->next;
}
83. 删除排序链表中的重复元素
ListNode* deleteDuplicates(ListNode* head) {
if(!head) return head;
ListNode* pre = head;
ListNode* cur = head->next;
while(cur)
{
if(cur->val != pre->val)
{
pre->next = cur;
pre = pre->next;
}
cur = cur->next;
}
if(pre->next)
{
pre->next = nullptr;
}
return head;
}
92. 反转链表 II
pair<ListNode*, ListNode*> Reverse(ListNode* l, ListNode* r){
ListNode* next_node = r->next;
ListNode* pre = next_node;
ListNode* p = l;
while(pre!=r){
ListNode* next = p->next;
p->next = pre;
pre = p;
p = next;
}
return {r,l};
}
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* p =dummy;
ListNode* l = nullptr;
ListNode* r = nullptr;
ListNode* pre = nullptr;
while(p){
if(left == 1){
pre = p;
}
if(right == 0){
r = p;
}
p = p->next;
left--;
right--;
}
l = pre->next;
pair<ListNode*, ListNode*> node = Reverse(l, r);
pre->next = node.first;
return dummy->next;
}
206. 反转链表
ListNode* reverseList(ListNode* head) {
if(!head||!head->next) return head;
ListNode* p = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return p;
}
ListNode* reverseList(ListNode* head) {
ListNode* cur = head;
ListNode* next = head;
ListNode* pre = nullptr;
while(cur)
{
auto temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
二叉树
94. 二叉树的中序遍历
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> s;
TreeNode* p = root;
while(!s.empty()||p)
{
if(p)
{
s.push(p);
p = p->left;
}
else
{
auto q = s.top();
s.pop();
res.push_back(q->val);
p = q->right;
}
}
return res;
}
98. 验证二叉搜索树
bool isValidBST(TreeNode* root) {
if(!root) return false;
stack<TreeNode*> s;
TreeNode* p = root;
bool first_flag = true;
int first = 0;
while(!s.empty()||p){
if(p){
s.push(p);
p = p->left;
} else {
p = s.top();
s.pop();
if(first_flag){
first = p->val;
first_flag = false;
} else {
if(p->val<=first){
return false;
}
first = p->val;
}
p = p->right;
}
}
return true;
}
101. 对称二叉树
bool isSymmetric(TreeNode* root) {
if(!root) return true;
return dfs(root->left,root->right);
}
bool dfs(TreeNode* p, TreeNode* q)
{
if(!p&&!q) return true;
if(!p) return false;
if(!q) return false;
if(p->val!=q->val) return false;
return dfs(p->left,q->right)&&dfs(p->right,q->left);
}
102. 二叉树的层序遍历
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
if(!root) return res;
queue<TreeNode*> q;
q.push(root);
q.push(nullptr);
vector<int> temp;
while(q.size())
{
auto t = q.front();
q.pop();
if(!t)
{
res.push_back(temp);
temp.clear();
if(q.size())
{
q.push(nullptr);
}
}
else
{
temp.push_back(t->val);
if(t->left)
{
q.push(t->left);
}
if(t->right)
{
q.push(t->right);
}
}
}
return res;
}
104. 二叉树的最大深度
int maxDepth(TreeNode* root) {
if(!root) return 0;
return max(maxDepth(root->left),maxDepth(root->right))+1;
}
105. 从前序与中序遍历序列构造二叉树
map<int,int> hash;
TreeNode* dfs(vector<int>& preorder, vector<int>& inorder, int pl,int pr,int il,int ir)
{
if(pl>pr||il>ir) return nullptr;
int index = hash[preorder[pl]];
int len = index - il;
TreeNode* root = new TreeNode(preorder[pl]);
root->left = dfs(preorder,inorder,pl+1,pl+len,il,index-1);
root->right = dfs(preorder,inorder,pl+len+1,pr,index+1,ir);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()!=inorder.size()||!preorder.size()||!inorder.size()) return nullptr;
for(int i=0;i<inorder.size();i++)
{
hash[inorder[i]] = i;
}
return dfs(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
}
108. 将有序数组转换为二叉搜索树
TreeNode* dfs(vector<int>& nums, int l, int r)
{
if(l>r)
{
return nullptr;
}
int mid = (r+l)>>1;
TreeNode* root = new TreeNode(nums[mid]);
root->left = dfs(nums,l,mid-1);
root->right = dfs(nums,mid+1,r);
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
int n = nums.size();
if(!n) return nullptr;
return dfs(nums,0,n-1);
}
110. 平衡二叉树
int dfs(TreeNode* root)
{
if(!root)
{
return 0;
}
int left = dfs(root->left);
int right = dfs(root->right);
if(abs(left-right)>1)
{
flag = false;
return max(left,right)+1;
}
return max(left,right)+1;
}
bool isBalanced(TreeNode* root) {
if(!root) return true;
dfs(root);
return flag;
}
bool flag = true;
113. 路径总和 II
void dfs(TreeNode* root, int targetSum, int sum, vector<int>& path, vector<vector<int>>& res) {
if(!root) {
return;
}
sum = sum + root->val;
path.push_back(root->val);
if(!root->left && !root->right && sum == targetSum){
res.push_back(path);
path.pop_back();
return;
}
if(root->left){
dfs(root->left, targetSum, sum, path, res);
}
if(root->right){
dfs(root->right, targetSum, sum, path, res);
}
path.pop_back();
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int>> res;
vector<int> path;
int sum = 0;
dfs(root, targetSum, sum, path, res);
return res;
}
124. 二叉树中的最大路径和
int dfs(TreeNode* root, int& max_path)
{
if(!root) return 0;
int left = max(dfs(root->left,max_path),0);
int right = max(dfs(root->right,max_path),0);
max_path = (left + right + root->val)>max_path? (left + right + root->val):max_path;
return max(left,right)+root->val;
}
int maxPathSum(TreeNode* root) {
int max_path = INT_MIN;
if(!root) return 0;
int sum = dfs(root, max_path);
return max_path;
}
129. 求根到叶子节点数字之和
void dfs(TreeNode* root, int &sum, int tmp){
if(!root){
return;
}
tmp = tmp * 10 + root->val;
if(!root->left && !root->right){
sum += tmp;
return;
}
if(root->left){
dfs(root->left, sum ,tmp);
}
if(root->right){
dfs(root->right, sum, tmp);
}
return;
}
int sumNumbers(TreeNode* root) {
if(!root){
return 0;
}
int sum = 0;
dfs(root, sum, 0);
return sum;
}
145. 二叉树的后序遍历
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> s;
TreeNode* p = root;
while(!s.empty()||p)
{
if(p)
{
res.push_back(p->val);
s.push(p);
p = p->right;
}
else
{
p = s.top();
s.pop();
p = p->left;
}
}
reverse(res.begin(),res.end());
return res;
}
199. 二叉树的右视图
vector<int> rightSideView(TreeNode* root) {
vector<int> res;
if(!root){
return res;
}
TreeNode* p = root;
queue<pair<TreeNode*, int>> q;
q.push({root,0});
int level = 0;
while(!q.empty()){
auto t = q.front();
q.pop();
if(t.second == res.size()) {
res.push_back(t.first->val);
level++;
} else {
res[t.second] = t.first->val;
}
if(t.first->left){
q.push({t.first->left, level});
}
if(t.first->right){
q.push({t.first->right, level});
}
}
return res;
}
236. 二叉树的最近公共祖先
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root) return nullptr;
if(root==p||root==q) return root;
auto left = lowestCommonAncestor(root->left,p,q);
auto right = lowestCommonAncestor(root->right,p,q);
if(left&&right)
{
return root;
}
if(left)
{
return left;
}
else
{
return right;
}
}
230. 二叉搜索树中第K小的元素
class Solution {
public:
void recursion(TreeNode* root,int& res,int& k)
{
if(!root)
return;
recursion(root->left,res,k);
k--;
if(k == 0)
{
res = root->val;
return;
}
recursion(root->right,res,k);
}
int kthSmallest(TreeNode* root, int k) {
int res;
recursion(root,res,k);
return res;
}
};
257. 二叉树的所有路径
void dfs(TreeNode* root, string& str)
{
string temp = to_string(root->val);
int n = temp.size();
str += temp + "->";
if(!root->left&&!root->right)
{
for(int i=0;i<2;i++)
{
str.pop_back();
}
res.push_back(str);
for(int j=0;j<n;j++)
{
str.pop_back();
}
return;
}
if(root->left)
{
dfs(root->left, str);
}
if(root->right)
{
dfs(root->right,str);
}
for(int k=0;k<n+2;k++)
{
str.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
if(!root) return res;
dfs(root,str);
return res;
}
private:
vector<string> res;
string str;
}
297. 二叉树的序列化与反序列化
TreeNode* deserialize(string data) {
int u = 0;
return dfs(data, u);
}
TreeNode* dfs(string data, int &u)
{
if(u == data.size()) return nullptr;
int k = u;
while(data[k]!=' ')
{
k++;
}
if(data[u]=='n')
{
u = k+1;
return nullptr;
}
int val = 0;
bool fu = false;
if(data[u] == '-')
{
fu = true;
u++;
}
else if(data[u] == '+')
{
fu = false;
u++;
}
else
{
fu = false;
}
for(int i=u;i<k;i++)
{
val = val*10 + data[i]-'0';
}
if(fu == true)
{
val = -1* val;
}
u = k+1;
TreeNode* root = new TreeNode(val);
root->left = dfs(data,u);
root->right = dfs(data,u);
return root;
}
617. 合并二叉树
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if(!t1) return t2;
if(!t2) return t1;
t1->left = mergeTrees(t1->left,t2->left);
t1->right = mergeTrees(t1->right,t2->right);
t1->val +=t2->val;
return t1;
}
二分查找
33. 搜索旋转排序数组
int search(vector<int>& nums, int target) {
int n = nums.size();
if(!n) return -1;
int l = 0;
int r = n -1;
while(l<=r)
{
int mid = (l+r)>>1;
if(nums[mid] == target)
{
return mid;
}
else if(nums[mid]>nums[r])
{
if(target>=nums[l]&&target<nums[mid])
{
r = mid;
}
else
{
l = mid+1;;
}
}
else
{
if(target>nums[mid]&&target<=nums[r])
{
l = mid+1;
}
else
{
r = mid-1;
}
}
}
return -1;
}
34. 在排序数组中查找元素的第一个和最后一个位置
vector<int> searchRange(vector<int>& nums, int target) {
int n = nums.size();
if(!n) return {-1,-1};
int l = 0;
int r = n-1;
vector<int> res;
while(l<r)
{
int mid = (l+r)>>1;
if(nums[mid]<target)
{
l = mid+1;
}
else
{
r = mid;
}
}
if(nums[l]!=target)
{
return {-1,-1};
}
int left = l;
l = 0;
r = n-1;
while(l<r)
{
int mid = (l+r+1)>>1;
if(nums[mid]>target)
{
r = mid-1;
}
else
{
l = mid;
}
}
int right = l;
return {left,right};
}
81. 搜索旋转排序数组 II
bool search(vector<int>& nums, int target) {
int n = nums.size();
if(!n) return false;
int l = 0;
int r = n-1;
while(l<=r)
{
int mid = (l+r)>>1;
if(nums[mid] == target)
{
return true;
}
if(nums[mid]==nums[r])
{
r--;
}
else if(nums[mid]<nums[r])
{
if(target>=nums[mid]&&target<=nums[r])
{
l = mid+1;
}
else
{
r = mid-1;
}
}
else
{
if(target>=nums[l]&&target<=nums[mid])
{
r = mid -1;
}
else
{
l = mid+1;
}
}
}
return false;
}
153. 寻找旋转排序数组中的最小值
int findMin(vector<int>& nums) {
int n = nums.size();
int l = 0;
int r = n-1;
while(l<r)
{
int mid = (l+r)>>1;
if(nums[mid]<nums[r])
{
r = mid;
}
else
{
l = mid + 1;
}
}
return nums[l];
}
154. 寻找旋转排序数组中的最小值 II
int findMin(vector<int>& nums)
{
int n = nums.size();
int l = 0;
int r = n-1;
while(l<r)
{
int mid = (l+r)>>1;
if(nums[mid] == nums[r])
{
r--;
}
else if(nums[mid]<nums[r])
{
r = mid;
}
else
{
l = mid +1;
}
}
return nums[l];
}
162. 寻找峰值
int findPeakElement(vector<int>& nums) {
int n = nums.size();
if(!n) return 0;
int l = 0;
int r = n-1;
while(l<r)
{
int mid = (l+r)>>1;
if(nums[mid]>=nums[mid+1])
{
r = mid;
}
else
{
l = mid+1;
}
}
return l;
}
排序
23. 合并K个升序链表
非递归
static bool Cmp(ListNode* a, ListNode* b){
return a->val > b->val;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, decltype(Cmp)*> q(Cmp);
if(lists.empty()){
return nullptr;
}
for(auto list: lists){
if(list!=nullptr){
q.push(list);
}
}
ListNode* dummy = new ListNode(-1);
ListNode* node = dummy;
while(!q.empty()){
auto t = q.top();
q.pop();
node->next = t;
if(t->next != nullptr){
q.push(t->next);
}
node = node->next;
}
return dummy->next;
}
归并
ListNode* MergeTwoList(ListNode* list1, ListNode* list2){
if(!list1){
return list2;
}
if(!list2){
return list1;
}
if(list1->val <= list2->val){
list1->next = MergeTwoList(list1->next, list2);
return list1;
} else {
list2->next = MergeTwoList(list1, list2->next);
return list2;
}
}
ListNode* Merge(vector<ListNode*>& lists, int begin, int end){
if(begin>end){
return nullptr;
}
if(begin==end){
return lists[begin];
}
int mid = (begin + end)>>1;
ListNode* node1 = Merge(lists, begin, mid);
ListNode* node2 = Merge(lists, mid+1, end);
ListNode* node = MergeTwoList(node1, node2);
return node;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
int n = lists.size();
if(!n){
return nullptr;
}
return Merge(lists, 0, n-1);
}
215. 数组中的第K个最大元素
堆排
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int, vector<int>, greater<int>> q;
for(int i=0;i<nums.size();++i){
if(q.size()<k){
q.push(nums[i]);
} else {
if(q.top() < nums[i]){
q.pop();
q.push(nums[i]);
}
}
}
return q.top();
}
快排
int Paitation(vector<int>& nums, int start, int end){
int i = start;
int j = i+1;
int k = nums[i];
while(j<=end){
if(nums[j] > k){
swap(nums[++i], nums[j]);
}
j++;
}
swap(nums[start], nums[i]);
return i;
}
int findKthLargest(vector<int>& nums, int k) {
int len = nums.size();
int left = 0;
int right = len-1;
int m = Paitation(nums, left, right);
while(m != k-1){
if(m<k-1){
left = m + 1;
m = Paitation(nums, left, right);
} else {
right = m - 1;
m = Paitation(nums, left, right);
}
}
return nums[k-1];
}
双指针
11. 盛最多水的容器
int maxArea(vector<int>& height) {
int n = height.size();
int i = 0;
int j = n-1;
int res =0;
while(i<j)
{
int temp = min(height[i],height[j]);
int sum = temp*(j-i);
res = max(sum, res);
if(height[i]<height[j])
{
i++;
}
else
{
j--;
}
}
return res;
}
15. 三数之和
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
if(n<3) return vector<vector<int>>();
sort(nums.begin(),nums.end());
vector<vector<int>> res;
for(int i=0;i<n-2;i++)
{
if(i==0||(i>0 && nums[i] != nums[i-1]))
{
int target = 0- nums[i];
int l = i+1;
int r = n-1;
while(l<r)
{
int temp = nums[l] + nums[r];
if(temp<target)
{
l++;
}
else if(temp>target)
{
r--;
}
else
{
res.push_back({nums[i],nums[l],nums[r]});
l++;
r--;
while(l<r&&nums[l]==nums[l-1]) l++;
while(l<r&&nums[r]==nums[r+1]) r--;
}
}
}
}
return res;
}
16. 最接近的三数之和
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int n = nums.size();
int best = 1e7;
auto update = [&](int cur){
if(abs(cur - target) < abs(best - target)){
best = cur;
}
};
for(int i=0;i<n-2;i++){
if(i>0 && nums[i] == nums[i-1]){
continue;
}
int left = i+1;
int right = n-1;
while(left < right){
int sum = nums[left] + nums[right] + nums[i];
update(sum);
if(sum == target){
return sum;
} else if(sum < target){
while(left<right && nums[left] == nums[left+1]){
left++;
}
left++;
} else {
while(left<right && nums[right] == nums[right-1]){
right--;
}
right--;
}
}
}
return best;
}
283. 移动零
void moveZeroes(vector<int>& nums) {
int n = nums.size();
if(!n) return;
int index = 0;
for(int i=0;i<n;i++)
{
if(nums[i]!=0)
{
nums[index] = nums[i];
index++;
}
}
for(;index<n;index++)
{
nums[index] = 0;
}
return;
}
字符串
28. 实现strStr
int strStr(string haystack, string needle) {
int n = haystack.size();
int m = needle.size();
for(int i=0;i+m<=n;i++){
bool is_find = true;
for(int j = 0;j<m;j++){
if(haystack[i+j]!= needle[j]){
is_find = false;
break;
}
}
if(is_find){
return i;
}
}
return -1;
}
49. 字母异位词分组
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> res;
int len = strs.size();
if(!len) return res;
map<multiset<char>, vector<string>> hash;
for(int i=0;i<len;i++)
{
multiset<char> st;
for(auto a: strs[i])
{
st.insert(a);
}
hash[st].push_back(strs[i]);
}
for(auto m:hash)
{
res.push_back(m.second);
}
return res;
}
392. 判断子序列
bool isSubsequence(string s, string t) {
int i = 0;
int j = 0;
int len1 = s.size();
int len2 = t.size();
while(i<len1&&j<len2)
{
if(s[i] == t[j])
{
i++;
}
j++;
}
if(i == len1)
{
return true;
}
return false;
}
贪心
55. 跳跃游戏
动态规划
bool canJump(vector<int>& nums) {
int n = nums.size();
if(!n) return false;
vector<bool> dp(n,false);
dp[0] = true;
for(int i=1;i<n;i++)
{
for(int j=i-1;j>=0;j--)
{
if(dp[j]&&nums[j]>=i-j)
{
dp[i] = true;
break;
}
}
}
return dp[n-1];
}
贪心
可以对每一个能作为起跳点的格子都尝试跳一次,把能跳到最远的距离 不断更新。如果可以一直跳到最后就成功了。
bool canJump(vector<int>& nums) {
int reach = 0 ;
for(int i=0;i<nums.size();i++)
{
if(reach<i||reach>=nums.size()-1) break;
reach = max(reach,nums[i]+i);
}
return reach>=nums.size()-1;
}
134 加油站
加油站
首先判断总油量是否小于总油耗,如果是则肯定不能走一圈。如果否,那肯定能跑一圈。接下来就是循环数组,从第一个站开始,计算每一站剩余的油量,如果油量为负了,就以这个站为起点从新计算。如果到达某一个点为负,说明起点到这个点中间的所有站点都不能到达该点。
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int cur = 0;
int total = 0;
int start = 0;
for(int i=0;i<gas.size();i++)
{
total += gas[i] - cost[i];
cur += gas[i] - cost[i];
if(cur < 0)
{
start = i+1;
cur = 0;
}
}
if(total>=0) return start;
else return -1;
}
135. 分发糖果
int candy(vector<int>& ratings) {
int n = ratings.size();
if(!n) return 0;
vector<int> nums(n,1);
for(int i=1;i<n;i++)
{
if(ratings[i]>ratings[i-1])
{
nums[i] = nums[i-1] + 1;
}
}
for(int i=n-1;i>=1;i--)
{
if(ratings[i-1]>ratings[i])
{
nums[i-1] = max(nums[i-1],nums[i]+1);
}
}
int res = 0;
for(auto num:nums)
{
res+= num;
}
return res;
}
435. 无重叠区间
static bool cmp(vector<int>a,vector<int>b){
return a[1]<b[1];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if (intervals.empty()) return 0;
//按照区间终结点,从小到大排序
sort(intervals.begin(), intervals.end(),cmp);
//获取最小的,区间终结点
int end = intervals[0][1];
int res = 0;
for (int i = 1; i < intervals.size(); ++i) {
//如果区间的起点,小于上一个区间的终点,说明有交集,要删除
if (intervals[i][0] < end) {
++res;
} else {
//没有交集,更新end
end = intervals[i][1];
}
}
return res;
}
659. 分割数组为连续子序列
bool isPossible(vector<int>& nums) {
unordered_map<int, int> nc, tail;
for(auto num : nums){
nc[num]++;
}
for(auto num : nums){
if(nc[num] == 0) continue;
else if(nc[num] > 0 && tail[num-1] > 0){//接在后面
nc[num]--;
tail[num-1]--;
tail[num]++;
}else if(nc[num] > 0 && nc[num+1] > 0 && nc[num+2] > 0){//能不能另外构造一个
nc[num]--;
nc[num+1]--;
nc[num+2]--;
tail[num+2]++;
}else{
return false;
}
}
return true;
}
945. 使数组唯一的最小增量
int minIncrementForUnique(vector<int>& A) {
if(A.size()==0) return 0;
sort(A.begin(),A.end());
int move = 0;
for(int i=1;i<A.size();i++)
{
if(A[i]<=A[i-1])
{
int add = A[i-1] + 1 - A[i];
move += add;
A[i] += add;
}
}
return move;
}
宽度优先遍历
127. 单词接龙(难)
深度优先遍历
39. 组合总和
unordered_set<string> hash;
void dfs(vector<int>& candidates, vector<int>& tmp, int begin, int target, vector<vector<int>>& res){
if(target<0){
return;
}
if(target == 0){
res.push_back(tmp);
return;
}
for(int i=begin;i<candidates.size();++i){
tmp.push_back(candidates[i]);
dfs(candidates, tmp, i, target - candidates[i], res);
tmp.pop_back();
}
return;
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> res;
vector<int> tmp;
dfs(candidates, tmp, 0, target, res);
return move(res);
}
130. 被围绕的区域
void dfs(int x,int y,vector<vector<char>>& vec)
{
int row = vec.size();
int col = vec[0].size();
if(x < 0 || y < 0 || x >= row || y >= col || vec[x][y] != 'O')
return;
vec[x][y] = '$';
dfs(x+1,y,vec);
dfs(x-1,y,vec);
dfs(x,y+1,vec);
dfs(x,y-1,vec);
}
void solve(vector<vector<char>>& board) {
if(board.empty()) return;
int row = board.size();
int col = board[0].size();
int i=0;
int j=0;
for(;j<col;j++)//上第一行
{
if(board[i][j]=='O')
dfs(i,j,board);
}
i = row-1;
j=0;
for(;j<col;j++)//下第一行
{
if(board[i][j]=='O')
dfs(i,j,board);
}
j = 0;
i=0;
for(;i<row;i++)//左第一列
{
if(board[i][j]=='O')
dfs(i,j,board);
}
j = col-1;
i=0;
for(;i<row;i++)//右第一列
{
if(board[i][j]=='O')
dfs(i,j,board);
}
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
{
if(board[i][j] == 'O')
board[i][j] = 'X';
}
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
{
if(board[i][j] == '$')
board[i][j] = 'O';
}
}
200. 岛屿的数量
void dfs(int i,int j,vector<vector<bool>>& visited,vector<vector<char>> & grid)
{
int n = grid.size();
int m = grid[0].size();
if(i<0||i>=n||j<0||j>=m)
{
return;
}
if(grid[i][j]=='0'||visited[i][j])
{
return;
}
visited[i][j]=true;
dfs(i-1,j,visited,grid);
dfs(i+1,j,visited,grid);
dfs(i,j-1,visited,grid);
dfs(i,j+1,visited,grid);
return;
}
int numIslands(vector<vector<char>>& grid) {
int n = grid.size();
if(!n) return 0;
int m = grid[0].size();
vector<vector<bool>> visited(n,vector<bool>(m,false));
int res = 0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(grid[i][j]=='1'&&!visited[i][j])
{
res++;
dfs(i,j,visited,grid);
}
}
}
return res;
}
宽度优先遍历
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int nr = grid.size();
if (!nr) return 0;
int nc = grid[0].size();
int num_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
grid[r][c] = '0';
queue<pair<int, int>> neighbors;
neighbors.push({r, c});
while (!neighbors.empty()) {
auto rc = neighbors.front();
neighbors.pop();
int row = rc.first, col = rc.second;
if (row - 1 >= 0 && grid[row-1][col] == '1') {
neighbors.push({row-1, col});
grid[row-1][col] = '0';
}
if (row + 1 < nr && grid[row+1][col] == '1') {
neighbors.push({row+1, col});
grid[row+1][col] = '0';
}
if (col - 1 >= 0 && grid[row][col-1] == '1') {
neighbors.push({row, col-1});
grid[row][col-1] = '0';
}
if (col + 1 < nc && grid[row][col+1] == '1') {
neighbors.push({row, col+1});
grid[row][col+1] = '0';
}
}
}
}
}
return num_islands;
}
};
回溯
51. N皇后
vector<vector<string>> res;
vector<vector<string>> solveNQueens(int n) {
vector<string> board(n, string(n, '.'));
backtrack(board, 0);
return res;
}
void backtrack(vector<string>& board, int row) {
// 触发结束条件
if (row == board.size()) {
res.push_back(board);
return;
}
int n = board[row].size();
for (int col = 0; col < n; col++) {
// 排除不合法选择
if (!isValid(board, row, col))
continue;
// 做选择
board[row][col] = 'Q';
// 进入下一行决策
backtrack(board, row + 1);
// 撤销选择
board[row][col] = '.';
}
}
bool isValid(vector<string>& board, int row, int col) {
int n = board.size();
// 检查列是否有皇后互相冲突
for (int i = 0; i < n; i++) {
if (board[i][col] == 'Q')
return false;
}
// 检查右上方是否有皇后互相冲突
for (int i = row - 1, j = col + 1;
i >= 0 && j < n; i--, j++) {
if (board[i][j] == 'Q')
return false;
}
// 检查左上方是否有皇后互相冲突
for (int i = row - 1, j = col - 1;
i >= 0 && j >= 0; i--, j--) {
if (board[i][j] == 'Q')
return false;
}
return true;
}
79. 单词搜索
bool dfs(int i, int j, int row, int col,int u, int l, string word, vector<vector<char>>& board,vector<vector<bool>>& visited)
{
if(u==l)
{
return true;
}
if(i<0||i>=row||j<0||j>=col||visited[i][j]||board[i][j]!=word[u])
{
return false;
}
visited[i][j] = true;
int dx[4] = {-1,0,1,0};//上、右、下、左
int dy[4] = {0,1,0,-1};
for(int d=0;d<4;d++)
{
int a = i+dx[d];
int b = j+dy[d];
if(dfs(a,b,row,col,u+1,l,word,board,visited))
{
return true;
}
}
visited[i][j] = false;
return false;
}
bool exist(vector<vector<char>>& board, string word) {
int row = board.size();
if(!row) return false;
int col = board[0].size();
int l = word.size();
vector<vector<bool>> visited(row,vector<bool>(col,false));
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
if(dfs(i,j,row,col,0,l,word,board,visited))
{
return true;
}
}
}
return false;
}
动态规划
硬币问题
int coinChange(vector<int>& coins, int amount) {
if(amount<0) return -1;
int Max = amount +1;
vector<int> dp(amount+1,Max);
dp[0] = 0;
for(auto coin:coins)
{
for(int j=coin;j<=amount;j++)
{
dp[j] = min(dp[j-coin]+1,dp[j]);
}
}
return dp[amount]>amount? -1: dp[amount];
}
5. 最长回文子串
string longestPalindrome(string s) {
int n = s.length();
int max_len = 0;
string res;
vector<vector<bool>> dp(n+1, vector<bool>(n+1, false));
for(int len=1;len<=n;len++){
for(int i=0;i+len-1<n;i++){
int j = i+len-1;
if(len == 1){
dp[i][j] = true;
} else if(len ==2){
dp[i][j] = s[i] == s[j];
} else {
if(s[i] == s[j]){
dp[i][j] = dp[i+1][j-1];
} else {
dp[i][j] = false;
}
}
if(dp[i][j] == true){
if(max_len < len){
max_len = len;
res = s.substr(i,len);
}
}
}
}
return res;
}
53. 最大子序和
int maxSubArray(vector<int>& nums) {
int n = nums.size();
if(!n) return 0;
int sum = 0;
vector<int> dp(n,0);
dp[0] = nums[0];
int res = dp[0];
for(int i=1;i<n;i++)
{
if(dp[i-1]<0)
{
dp[i] = nums[i];
}
else
{
dp[i] = nums[i] + dp[i-1];
}
res = max(res,dp[i]);
}
return res;
}
62. 不同路径
int uniquePaths(int m, int n) {
if(!m||!n) return 0;
vector<vector<int>> dp(n,vector<int>(m,1));
for(int i=1;i<n;i++)
{
for(int j=1;j<m;j++)
{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[n-1][m-1];
}
64. 最小路径和
int minPathSum(vector<vector<int>>& grid) {
int n = grid.size();
if(!n) return 0;
int m = grid[0].size();
vector<vector<int>> dp(n,vector<int>(m,0));
dp[0][0] = grid[0][0];
for(int i=1;i<n;i++)
{
dp[i][0] = dp[i-1][0] + grid[i][0];
}
for(int j=1;j<m;j++)
{
dp[0][j] = dp[0][j-1] + grid[0][j];
}
for(int i=1;i<n;i++)
{
for(int j =1;j<m;j++)
{
dp[i][j] = min(dp[i][j-1],dp[i-1][j]) + grid[i][j];
}
}
return dp[n-1][m-1];
}
72. 编辑距离
120. 三角形的最小路径和
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
vector<vector<int>> dp(n,vector<int>());
for(int i=0;i<n;i++)
{
dp[i].resize(i+1,0);
}
for(int i=0;i<n;i++)
{
dp[n-1][i] = triangle[n-1][i];
}
for(int i = n-2;i>=0;i--)
{
for(int j=0;j<=i;j++)
{
dp[i][j] = min(dp[i+1][j],dp[i+1][j+1]) + triangle[i][j];
}
}
return dp[0][0];
}
121. 买卖股票的最佳时机
贪心
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n<=1) return 0;
int res = 0;
int minv = prices[0];
int temp = 0;
for(int i=1;i<n;i++) {
temp = prices[i] - minv;
minv = min(minv,prices[i]);
res = max(res,temp);
}
return res;
}
动态规划
122. 买卖股票的最佳时机 II
123. 买卖股票的最佳时机 III
139. 单词拆分
bool wordBreak(string s, vector<string>& wordDict) {
int len = wordDict.size();
unordered_set<string> hash;
for(auto word: wordDict){
hash.insert(word);
}
int n = s.size();
vector<bool> dp(n+1, false);
dp[0] = true;
for(int i=1;i<=n;++i){
for(int j=0;j<i;j++){
if(dp[j] && hash.find(s.substr(j, i-j))!=hash.end()){
dp[i] = true;
break;
}
}
}
return dp[n];
}
152. 乘积最大子数组
乘积最大子数组
在这里插入图片描述
198 打家劫舍
int rob(vector<int>& nums) {
int n = nums.size();
if(!n) return 0;
if(n==1) return nums[0];
vector<int> dp(n,0);
int res = 0;
dp[0] = nums[0];
dp[1] = max(nums[0],nums[1]);
for(int i=2;i<n;i++)
{
dp[i] = max(dp[i-1],nums[i] + dp[i-2]);
}
return dp[n-1];
}
221. 最大正方形
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return 0;
}
int maxSide = 0;
int rows = matrix.size(), columns = matrix[0].size();
vector<vector<int>> dp(rows, vector<int>(columns));
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (matrix[i][j] == '1') {
if (i == 0 || j == 0) {
dp[i][j] = 1;
} else {
dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
}
maxSide = max(maxSide, dp[i][j]);
}
}
}
int maxSquare = maxSide * maxSide;
return maxSquare;
}
};
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/maximal-square/solution/zui-da-zheng-fang-xing-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
300. 最长上升子序列
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
if(n<=1) return n;
vector<int> dp(n,1);
int res = 0;
for(int i=1;i<n;i++)
{
for(int j = i-1;j>=0;j--)
{
if(nums[i]>nums[j])
{
dp[i] = max(dp[j] + 1,dp[i]);
}
}
res = max(res,dp[i]);
}
return res;
}
312. 戳气球
int maxCoins(vector<int>& nums) {
int n=nums.size();
nums.insert(nums.begin(),1);
nums.push_back(1);
vector<vector<int>> dp(n+2, vector<int>(n+2, 0));
for(int len=1;len<=n;len++)
{
for(int start=1;start+len-1<=n;start++)
{
int end=start+len-1;
if(len==1)
{
dp[start][end] = nums[start-1]*nums[start]*nums[start+1];
}
else
{
for(int k = start; k<=end; k++)
{
dp[start][end] = max(dp[start][end], dp[start][k-1]+dp[k+1][end]+nums[start-1]*nums[k]*nums[end+1]);
}
}
}
}
return dp[1][n];
}
322. 零钱兑换
int coinChange(vector<int>& coins, int amount) {
if(coins.empty()||amount==0) return 0;
vector<int> dp(amount+1, INT_MAX);
dp[0] = 0;
for(int i = 1; i<=amount; i++)
{
for(int j = 0; j<coins.size(); j++)
{
if(coins[j]<=i&&dp[i-coins[j]]!=INT_MAX)
{
dp[i] = min(dp[i], dp[i-coins[j]]+1);
}
}
}
return dp[amount]==INT_MAX?-1:dp[amount];
}
329. 矩形中的最长递增路径
int dfs(int x,int y,const vector<vector<int>>& vec,vector<vector<int>>& dp)
{
if(dp[x][y] != 0)
return dp[x][y];
int row = vec.size();
int col = vec[0].size();
dp[x][y] = 1;
if(x > 0 && vec[x-1][y] < vec[x][y])
{
int cnt = dfs(x-1,y,vec,dp) + 1;
dp[x][y] = max(dp[x][y],cnt);
}
if(x < row - 1 && vec[x+1][y] < vec[x][y])
{
int cnt = dfs(x+1,y,vec,dp) + 1;
dp[x][y] = max(cnt,dp[x][y]);
}
if(y > 0 && vec[x][y-1] < vec[x][y])
{
int cnt = dfs(x,y-1,vec,dp) + 1;
dp[x][y] = max(dp[x][y],cnt);
}
if(y < col - 1 && vec[x][y+1] < vec[x][y])
{
int cnt = dfs(x,y+1,vec,dp) + 1;
dp[x][y] = max(dp[x][y],cnt);
}
return dp[x][y];
}
int longestIncreasingPath(vector<vector<int>>& matrix) {
if(matrix.empty()) return 0;
int row = matrix.size();
int col = matrix[0].size();
vector<vector<int>> dp(row,vector<int>(col,0));
int res = INT_MIN;
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
{
int a = dfs(i,j,matrix,dp);
res = max(res,a);
}
return res;
}
334. 递增的三元子序列
bool increasingTriplet(vector<int>& nums) {
int n = nums.size();
if(!n) return false;
vector<int> dp(n,1);
for(int i=1;i<n;i++)
{
for(int j = i-1;j>=0;j--)
{
if(nums[j]<nums[i])
{
dp[i] = max(dp[i],dp[j]+1);
}
if(dp[i]>=3)
{
return true;
}
}
}
return false;
}
376. 摆动序列
int wiggleMaxLength(vector<int>& nums) {
if(nums.empty()) return 0;
int n = nums.size();
vector<int> dp1(n, 1); // 结尾最后两个递增的摆动序列
vector<int> dp2(n, 1); // 结尾最后两个递减的摆动序列
for(int i = 1; i<nums.size(); i++)
{
for(int j = i-1; j>=0; j--)
{
if(nums[j]<nums[i])
{
dp1[i] = max(dp1[i], dp2[j]+1);
}
else if(nums[j]>nums[i])
{
dp2[i] = max(dp2[i], dp1[j]+1);
}
}
}
return max(dp1.back(), dp2.back());
}
并查集
574. 朋友圈
class UnionSet
{
public:
UnionSet(int n)
{
for(int i=0;i<n;i++)
{
fatherMap[i] = i;
sizeMap[i] = 1;
}
}
int findhead(int i)
{
int head;
if(fatherMap[i] == i)
{
return i;
}
else
{
head = findhead(fatherMap[i]);
}
return head;
}
void Union(int i, int j)
{
int head1 = findhead(i);
int head2 = findhead(j);
if(head1 == head2)
{
return;
}
if(sizeMap[head1] > sizeMap[head2])
{
fatherMap[head2] = head1;
sizeMap[head1] += sizeMap[head2];
sizeMap.erase(head2);
}
else
{
fatherMap[head1] = head2;
sizeMap[head2] += sizeMap[head1];
sizeMap.erase(head1);
}
return;
}
int size()
{
return sizeMap.size();
}
private:
unordered_map<int,int> fatherMap;
unordered_map<int,int> sizeMap;
};
class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
if(M.size()==0) return 0;
int n = M[0].size();
UnionSet unionset(n);
for(int i=0;i<n;i++)
{
for(int j = i+1;j<n;j++)
{
if(M[i][j])
{
unionset.Union(i,j);
}
}
}
return unionset.size();
}
};
684. 冗余连接
class UnionSet
{
public:
UnionSet(int n)
{
for(int i=0;i<n;i++)
{
fatherMap[i] = i;
sizeMap[i] = 1;
}
}
bool isSame(int i, int j)
{
return findhead(i) == findhead(j);
}
int findhead(int i)
{
int head;
if(fatherMap[i] == i)
{
return i;
}
else
{
head = findhead(fatherMap[i]);
}
return head;
}
void Union(int i, int j)
{
int head1 = findhead(i);
int head2 = findhead(j);
if(head1 == head2)
{
return;
}
if(sizeMap[head1]>sizeMap[head2])
{
fatherMap[head2] = head1;
sizeMap[head1] += sizeMap[head2];
}
else
{
fatherMap[head1] = head2;
sizeMap[head2] += sizeMap[head1];
}
return;
}
private:
unordered_map<int,int> fatherMap;
unordered_map<int,int> sizeMap;
};
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int n = edges.size();
if(!n) return vector<int>();
UnionSet unionset(n);
for(auto edge: edges)
{
if(!unionset.isSame(edge[0],edge[1]))
{
unionset.Union(edge[0],edge[1]);
continue;
}
return edge;
}
return vector<int>();
}
拓扑排序
207. 课程表
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> graph(numCourses,vector<int>());
vector<int> degree(numCourses,0);
for(int i=0;i<prerequisites.size();i++)
{
graph[prerequisites[i][1]].push_back(prerequisites[i][0]);
degree[prerequisites[i][0]]++;
}
queue<int> q;
for(int i=0;i<degree.size();i++)
{
if(degree[i]==0)
{
q.push(i);
}
}
int cnt = 0;
while(q.size())
{
auto t = q.front();
q.pop();
cnt++;
for(int i=0;i<graph[t].size();i++)
{
degree[graph[t][i]]--;
if(degree[graph[t][i]]==0)
{
q.push(graph[t][i]);
}
}
}
if(cnt == numCourses)
{
return true;
}
return false;
}
火星文字典
#include <vector>
#include <string>
#include <queue>
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string s;
getline(cin,s);
stringstream ss(s);
vector<string> nums;
while (ss >> s)
{
nums.push_back(s);
}
vector<vector<int>> graph(26, vector<int>());
vector<int> degree(26,-1);
for (int i = 0; i < nums.size(); i++)
{
for (int j = 0; j < nums[i].size(); j++)
{
degree[nums[i][j] - 'a'] = 0;
}
}
int cnt = 0;
for (int i = 0; i < degree.size(); i++)
{
if (degree[i] == 0)
{
cnt++;
}
}
for (int i = 1; i < nums.size(); i++)
{
for (int j = 0; j < nums[i-1].size(); j++)
{
char from = nums[i - 1][j];
char to = nums[i][j];
if (from == to) continue;
graph[from - 'a'].push_back(to - 'a');
degree[to - 'a']++;
break;
}
}
queue<int> q;
int zero_num = 0;
for (int i = 0; i < degree.size(); i++)
{
if (degree[i] == 0)
{
zero_num++;
q.push(i);
}
}
vector<char> res;
while (q.size())
{
auto t = q.front();
q.pop();
res.push_back(t + 'a');
for (int i = 0; i < graph[t].size(); i++)
{
int to = graph[t][i];
degree[to]--;
if (degree[to] == 0)
{
q.push(to);
}
}
}
if(zero_num>1)
{
cout<< "invalid";
return 0;
}
if (res.size() != cnt)
{
cout << "invalid";
}
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
}
return 0;
}
单调栈
42. 接雨水
int trap(vector<int>& height) {
int n = height.size();
stack<int> min_stack;
int res = 0;
for(int i=0;i<n;i++){
while(min_stack.size() && height[i] > height[min_stack.top()]){
int t = min_stack.top();
min_stack.pop();
if(min_stack.empty()){
break;
}
int l = min_stack.top();
int water = (min(height[i], height[l]) - height[t])*(i-l-1);
res += water;
}
min_stack.push(i);
}
return res;
}
动态规划
对于下标 ii,下雨后水能到达的最大高度等于下标 ii 两边的最大高度的最小值,下标 ii 处能接的雨水量等于下标 ii 处的水能到达的最大高度减去 。
int trap(vector<int>& height) {
int n = height.size();
if (n == 0) {
return 0;
}
vector<int> leftMax(n);
leftMax[0] = height[0];
for (int i = 1; i < n; ++i) {
leftMax[i] = max(leftMax[i - 1], height[i]);
}
vector<int> rightMax(n);
rightMax[n - 1] = height[n - 1];
for (int i = n - 2; i >= 0; --i) {
rightMax[i] = max(rightMax[i + 1], height[i]);
}
int ans = 0;
for (int i = 0; i < n; ++i) {
ans += min(leftMax[i], rightMax[i]) - height[i];
}
return ans;
}
84. 柱状图中最大的矩形
int largestRectangleArea(vector<int>& heights) {
int ans = 0;
heights.insert(heights.begin(), 0);
heights.push_back(0);
stack<int> max_stack;
int res = 0;
for(int i=0;i<heights.size();i++){
while(max_stack.size()>0 && heights[i] < heights[max_stack.top()]){
int cur = max_stack.top();
max_stack.pop();
int right = i - 1;
int left = max_stack.top() + 1;
int area = (right - left +1) * heights[cur];
res = max(res, area);
}
max_stack.push(i);
}
return res;
}
前缀树
208. 实现 Trie (前缀树)
struct node
{
int tail;
node* next[26];
node()
{
tail = 0;
for(int i=0;i<26;i++)
next[i] = nullptr;
}
};
class Trie {
public:
/** Initialize your data structure here. */
Trie() {
root = nullptr;
}
/** Inserts a word into the trie. */
void insert(string word) {
if(word.empty())
return;
if(!root)
root = new node();
node* p = root;
for(int i=0;i<word.size();i++)
{
int a = word[i] - 'a';
if(!p->next[a])
{
p->next[a] = new node();
}
p = p->next[a];
}
p->tail++;
}
/** Returns if the word is in the trie. */
bool search(string word) {
if(word.empty()) return false;
if(!root) return false;
node* p = root;
for(int i=0;i<word.size();i++)
{
int a = word[i] - 'a';
if(!p->next[a])
{
return false;
}
p = p->next[a];
}
if(p->tail>0)
return true;
else
return false;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
if(prefix.empty()) return false;
if(!root) return false;
node* p = root;
for(int i=0;i<prefix.size();i++)
{
int a = prefix[i] - 'a';
if(!p->next[a])
{
return false;
}
p = p->next[a];
}
return true;
}
private:
node* root;
};
字符串的唯一识别
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
struct node
{
int tail;
int path;
node* next[26];
node()
{
tail = 0;
path = 0;
for (int i = 0; i < 26; i++)
next[i] = nullptr;
}
};
class Trie {
public:
/** Initialize your data structure here. */
Trie() {
root = nullptr;
}
/** Inserts a word into the trie. */
void insert(string word) {
if (word.empty())
return;
if (!root)
root = new node();
node* p = root;
for (int i = 0; i < word.size(); i++)
{
int a = word[i] - 'a';
if (!p->next[a])
{
p->next[a] = new node();
}
p->path++;
p = p->next[a];
}
p->tail++;
}
/** Returns if the word is in the trie. */
bool search(string word) {
if (word.empty()) return false;
if (!root) return false;
node* p = root;
for (int i = 0; i < word.size(); i++)
{
int a = word[i] - 'a';
if (!p->next[a])
{
return false;
}
p = p->next[a];
}
if (p->tail > 0)
return true;
else
return false;
}
string findfirst(string word) {
if (word.empty()) return "";
if (!root) return "";
string res;
node* p = root;
for (int i = 0; i < word.size(); i++)
{
int a = word[i] - 'a';
if (!p->next[a])
{
return "";
}
p = p->next[a];
res += word[i];
if (p->path == 1)
{
return res;
}
}
return res;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
if (prefix.empty()) return false;
if (!root) return false;
node* p = root;
for (int i = 0; i < prefix.size(); i++)
{
int a = prefix[i] - 'a';
if (!p->next[a])
{
return false;
}
p = p->next[a];
}
return true;
}
private:
node* root;
};
int main()
{
int n;
cin >> n;
string s;
vector<string> str;
Trie tr;
for (int i = 0; i < n; i++)
{
cin >> s;
tr.insert(s);
str.push_back(s);
}
for (int i = 0; i < n; i++)
{
string tr_s = tr.findfirst(str[i]);
cout << tr_s << endl;
}
return 0;
}
最小生成树
Prim算法
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
const int max_n = 105;
const int INF = 0x3f3f3f3f;
// st[i] 表示点i是否在当前生成树集合中
// dist[i] 表示点i到当前集合的最短边的长度
// g[i][j] 表示点i和点j之间边的长度
// 返回值:最小生成树中所有边的总长度
int g[max_n][max_n];
int st[max_n];
int dist[max_n];
int N;
int Prim()
{
int res = 0;
for (int i = 1; i <= N; i++)
{
dist[i] = INF;
st[i] = false;
}
dist[1] = 0;
for (int i = 1; i <= N; i++)
{
int id = -1;
int min_dist = INF;
for (int j = 1; j <= N; j++)
{
if (!st[j] && dist[j] < min_dist)
{
id = j;
min_dist = dist[j];
}
}
st[id] = true;
res += min_dist;
for (int j = 1; j <= N; j++)
{
if (!st[j])
{
dist[j] = min(dist[j], g[id][j]);
}
}
}
return res;
}
int main()
{
int n;
cin >> N >> n;
int a, b, c;
for (int j = 1; j <= N; j++)
{
for (int k = 1; k <= N; k++)
{
g[j][k] = INF;
}
}
for (int i = 0; i < n; i++)
{
cin >> a >> b >> c;
g[a][b] = min(g[b][a], c);
g[b][a] = min(g[b][a], c);
}
int res = Prim();
cout<<res;
return 0;
}
Kruskal算法
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
const int max_n = 105;
int father[max_n];
//边的信息
struct Edge
{
int a, b, v;
bool operator< (const Edge &W) const
{
return v < W.v;
}
};
// 所有边存储在 Edge edges[M];
Edge edge[max_n];
int n;
int m;
// 并查集——寻找当前集合的代表元素
int find(int x)
{
if (father[x] != x)
{
father[x] = find(father[x]);
}
return father[x];
}
// 函数返回最小生成树中所有边的总长度
int Kruskal()
{
int res = 0;
// 初始化并查集代表元素
for (int i = 1; i <= n; i++)
{
father[i] = i;
}
sort(edge, edge + m);
for (int i = 0; i < m; i++)
{
int a = edge[i].a;
int b = edge[i].b;
if (find(a) != find(b))
{
res += edge[i].v;
father[find(a)] = find(b);
}
}
return res;
}
int main()
{
cin >> n >> m;
int a, b, c;
for (int i = 0; i < m; i++)
{
cin >> edge[i].a >> edge[i].b>> edge[i].v;
}
int res = Kruskal();
cout<<res;
return 0;
}
数学
7. 整数反转
int reverse(int x) {
int res=0;
while(x!=0){
int tmp = x%10;
//判断是否 大于 最大32位整数
if (res>214748364 || (res==214748364 && tmp>7)) {
return 0;
}
//判断是否 小于 最小32位整数
if (res<-214748364 || (res==-214748364 && tmp<-8)) {
return 0;
}
res = res*10 + tmp;
x = x/10;
}
return res;
}
9. 回文数
bool isPalindrome(int x) {
if(x<0){
return false;
}
long long revert = 0;
int tmp = x;
while(tmp){
revert = revert* 10 + tmp%10;
tmp = tmp/10;
}
if(revert == x){
return true;
} else{
return false;
}
}
50. 快速幂
double quickMul(double x, long long N)
{
double res = 1.0;
double t = x;
while(N>0)
{
if(N&1)
{
res *= t;
}
t *= t;
N = N>>1;
}
return res;
}
double myPow(double x, int n) {
long long N = n;
return N>0?quickMul(x,N):1.0/quickMul(x,-N);
}
69. x的平方根
int mySqrt(int x) {
int l = 0;
int r = x;
int ans = -1;
while(l<=r){
int mid = l + (r-l) /2;
if((long long)mid*mid == x){
return mid;
}
else if( (long long)mid*mid<x){
ans = mid;
l = mid + 1;
} else {
r = mid -1;
}
}
return ans;
}
415. 字符串相加
string addStrings(string num1, string num2) {
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
int n = num1.size();
int m = num2.size();
int len = max(m, n);
vector<int> dp(len, 0);
for(int i=0;i<n;i++){
dp[i] += (num1[i] - '0');
}
for(int i=0;i<m;i++){
dp[i] += (num2[i] - '0');
}
string res;
int carry = 0;
for(int i=0;i<len;i++){
res += (dp[i] + carry)%10 + '0';
carry = (dp[i] + carry)/10;
}
if(carry>0){
res += carry + '0';
}
reverse(res.begin(), res.end());
return res;
}
最短路
模板
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010, M = 2000010, INF = 1000000000;
int n, m;
int g[N][N], dist[N]; // g[][]存储图的邻接矩阵, dist[]表示每个点到起点的距离
bool st[N]; // 存储每个点的最短距离是否已确定
void dijkstra()
{
for (int i = 1; i <= n; i++) dist[i] = INF;
dist[1] = 0;
for (int i = 0; i < n; i++)
{
int id, mind = INF;
for (int j = 1; j <= n; j++)
if (!st[j] && dist[j] < mind)
{
mind = dist[j];
id = j;
}
st[id] = 1;
for (int j = 1; j <= n; j++) dist[j] = min(dist[j], dist[id] + g[id][j]);
}
}
int main()
{
cin >> m >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
g[i][j] = INF;
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b], c);
}
dijkstra();
cout << dist[n] << endl;
return 0;
}
PTA甲级1003
题意,给我们n个点,有m条路,每个点都有一个权值,每一条路都有自己的长度且都是双向的路,让我们求从起点s,到终点e之间的最短路径数量,且求出在这些最短路程中所有点权值和最大的一条的权值和。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
const int maxn = 1010;
const int INF = 0x3f3f3f3f;
bool visit[maxn];
int city[maxn];//图的顶点值
int cost[maxn][maxn];//每条边的权重
int dist[maxn];//从V0到每条边的权重
int amount[maxn];
int pathCount[maxn];
int n, m;
void init()
{
for (int i = 0; i < n; i++)
{
visit[i] = false;
pathCount[i] = 0;
amount[i] = 0;
for (int j = 0; j < n; j++)
{
cost[i][j] = INF;
}
}
}
void dijkstra(int v0)
{
//v0直接到自己最短
pathCount[v0] = 1;
amount[v0] = city[v0];
visit[v0] = true;
//生成最初的dist数组
for (int i = 0; i < n; i++)
{
dist[i] = cost[v0][i];
if (dist[i] != INF&&i!=v0)
{
amount[i] = amount[v0] + city[i];
pathCount[i] = 1;
}
}
for (int i = 0; i < n - 1; i++)
{
int min_dist = INF;
int pos = -1;
for (int j = 0; j < n; j++)
{
if (!visit[j] && dist[j] < min_dist)
{
min_dist = dist[j];
pos = j;
}
}
visit[pos] = true;
for (int j = 0; j < n; j++)
{
//松弛,通过pos到j更近
if (!visit[j] && dist[pos] + cost[pos][j]<dist[j])
{
dist[j] = dist[pos] + cost[pos][j];//通过pos到j
amount[j] = amount[pos] + city[j];//累加顶点的值
pathCount[j] = pathCount[pos]; //到j的最短路径数即到pos的最短路径数
}
else if (!visit[j] && dist[pos] + cost[pos][j] == dist[j])
{
pathCount[j] += pathCount[pos];//增加从pos到j的路径数量
if (amount[pos] + city[j] > amount[j])//更新较大的amount
{
amount[j] = amount[pos] + city[j];
}
}
}
}
return;
}
int main()
{
int v0, vt;
cin >> n >> m >> v0 >> vt;
init();
for (int i = 0; i < n; i++)
{
cin >> city[i];
}
int t1, t2, t;
for (int i = 0; i < m; i++)
{
cin >> t1 >> t2 >> t;
cost[t1][t2] = cost[t2][t1] = t;
}
dijkstra(v0);
cout << pathCount[vt] << " " << amount[vt] << endl;
return 0;
}
743. 网络延迟时间
int INF = 0x3f3f3f3f;
void distkstra(int K,vector<vector<int>>& cost, vector<int> &dist,vector<bool> &visit)
{
visit[K] = true;
dist[K] = 0;
int N = dist.size()-1;
for(int i=1;i<N;i++)
{
int min_dist = INF;
int pos = 0;
for(int j = 1;j<N+1;j++)
{
if(!visit[j]&&dist[j]<min_dist)
{
min_dist = dist[j];
pos = j;
}
}
visit[pos] = true;
for(int j =1;j<N+1;j++)
{
if(!visit[j]&&cost[pos][j] + dist[pos]<dist[j])
dist[j] = min(dist[j], cost[pos][j] + dist[pos]);
}
}
return;
}
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
int n = times.size();
vector<vector<int>> cost(N+1,vector<int>(N+1,INF));
for(int i=0;i<n;i++)
{
cost[times[i][0]][times[i][1]] = times[i][2];
}
vector<int> dist(N+1,INF);
for(int i=1;i<N+1;i++)
{
dist[i] = cost[K][i];
}
vector<bool> visit(N+1,false);
distkstra(K,cost,dist,visit);
int max_time = -1;
for(int i=1;i<N+1;i++)
{
max_time = max(max_time, dist[i]);
}
if (max_time == INF)
{
return -1;
}
return max_time;
}
其它
146. LRU 缓存
class LRUCache {
public:
LRUCache(int capacity):cap(capacity) {
}
int get(int key) {
auto it = mp.find(key);
if (it == mp.end()) return -1;
auto target_it = it->second;
pair<int, int> n {target_it->first, target_it->second};
cache.push_front(n);
cache.erase(target_it);
mp.erase(key);
mp.emplace(key, cache.begin());
return n.second;
}
void put(int key, int value) {
auto it = mp.find(key);
if (it != mp.end()) {
cache.erase(it->second);
mp.erase(key);
}
pair<int, int> n {key, value};
cache.push_front(n);
mp.emplace(key, cache.begin());
if (cache.size() > cap) {
mp.erase(cache.back().first);
cache.pop_back();
}
}
private:
size_t cap = 0;
list<pair<int, int>> cache;
unordered_map<int, list<pair<int, int>>::iterator> mp;
};
背包九讲
背包
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int v[N],w[N];
int f[N][N];
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
f[i][j] = f[i-1][j];
if(j>=v[i])
{
f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
}
}
int res = 0;
for(int j=0;j<=m;j++)
{
res = max(res,f[n][j]);
}
cout << res <<endl;
return 0;
}
一维解法
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int v[N],w[N];
int f[N];
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)//物品
{
for(int j=m;j>=v[i];j--)//
{
f[j] = max(f[j],f[j-v[i]]+w[i]);
}
}
cout << f[m] <<endl;
return 0;
}
完全背包
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,m;
int v[N],w[N];
int f[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>v[i]>>w[i];
}
for(int i=1;i<=n;i++)//物品
{
for(int j = v[i];j<=m;j++)//体积
{
f[j] = max(f[j],f[j-v[i]]+w[i]);
}
}
cout<<f[m]<<endl;
return 0;
}
多重背包
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int n,m;
const int N = 1010;
int f[N];
int v,w,s;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>v>>w>>s;
for(int j = m ; j>=v ; j--)
{
for(int k=1;k<=s&&k*v<=j;k++)
f[j] = max(f[j],f[j-k*v]+k*w);
}
}
cout<<f[m]<<endl;
return 0;
}
//二进制优化版本
#include <iostream>
#include <vector>
#include <string>
using namespace std;
const int N = 2010;
int f[N];
struct Good
{
int v;
int w;
};
int main()
{
int n,m;
vector<Good> goods;
cin>>n>>m;
for(int i=0;i<n;i++)
{
int v,w,s;
cin>>v>>w>>s;
for(int k=1;k<=s;k*=2)
{
s -= k;
goods.push_back({k*v,k*w});
}
if(s>0)
{
goods.push_back({s*v,s*w});
}
}
for(auto good: goods)
{
for(int j=m;j>=good.v;j--)
{
f[j] = max(f[j],f[j-good.v]+good.w);
}
}
cout<<f[m]<<endl;
return 0;
}
树形dp
338. 比特位计数
class Solution {
public:
vector<int> countBits(int num) {
vector<int> res(num+1, 0);
for(int i = 1; i<=num; i++)
{
if(i%2==0)
{
res[i] = res[i/2];
}
else
{
res[i] = res[i/2] + 1;
}
}
return res;
}
};
记忆化搜索
567出界的路径数
class Solution {
public:
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int findPaths(int m, int n, int N, int i, int j) {
vector<vector<vector<int>>> dp(m, vector<vector<int>>(n, vector<int>(N+1, -1)));
return dfs(m, n, N, dp, i, j);
}
int dfs(int m, int n, int k, vector<vector<vector<int>>>& dp, int x, int y)
{
int& v = dp[x][y][k];
if(v!=-1)
{
return v;
}
v = 0;
if(!k)
{
return v;
}
for(int i = 0; i<4; i++)
{
int a = x + dx[i];
int b = y + dy[i];
if(a<0||a>=m||b<0||b>=n)
{
v++;
}
else
{
v +=dfs(m, n, k-1, dp, a, b);
}
v%=1000000007;
}
return v;
}
};
总结
提示:这里对文章进行总结:
例如:添加链接描述以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。