【LeetCode】 热题 HOT 100代码汇总
记录LeetCode 热题 HOT 100 代码
1. 两数之和
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> hash;
for(int i = 0; i < nums.size(); i ++ )
{
int r = target - nums[i];
if(hash.count(r)) return {hash[r], i};
hash[nums[i]] = i;
}
return {};
}
};
2. 两数相加
/**
* 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* addTwoNumbers(ListNode* l1, ListNode* l2) {
auto dummy = new ListNode(-1), cur = dummy;
int t = 0;
while(l1 || l2 || t)
{
if(l1) t += l1->val, l1 = l1->next;
if(l2) t += l2->val, l2 = l2->next;
cur = cur->next = new ListNode(t % 10);
t /= 10;
}
return dummy->next;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/1437840/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3. 无重复字符的最长子串
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> hash;
int res = 0;
for(int i = 0, j = 0; i < s.size(); i ++ )
{
hash[s[i]] ++ ;
while(hash[s[i]] > 1) hash[s[j ++ ]] -- ;
res = max(res, i - j + 1);
}
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/1938829/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
4. 寻找两个正序数组的中位数
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int tot = nums1.size() + nums2.size();
if(tot % 2 == 0)
{
int left = find(nums1, 0, nums2, 0, tot / 2);
int right = find(nums1, 0, nums2, 0, tot / 2 + 1);
return (left + right) / 2.0;
}
else
return find(nums1, 0, nums2, 0, tot / 2 + 1);
}
int find(vector<int>& nums1, int i, vector<int>& nums2, int j, int k)
{
if(nums1.size() - i > nums2.size() - j) return find(nums2, j, nums1, i, k);
if(k == 1)
{
if(nums1.size() == i)
return nums2[j];
else
return min(nums1[i], nums2[j]);
}
if(nums1.size() == i) return nums2[j + k - 1];
int si = min((int)nums1.size(), i + k / 2), sj = j + k - k / 2;
if(nums1[si - 1] > nums2[sj - 1]) return find(nums1, i, nums2, sj, k - (sj - j));
else return find(nums1, si, nums2, j, k - (si - i));
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/2005352/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
5. 最长回文子串
class Solution {
public:
string longestPalindrome(string s) {
string res;
for(int i = 0; i < s.size(); i ++ )
{
//枚举字符串长度是奇数的情况
int l = i - 1, r = i + 1;
while(l >= 0 && r < s.size() && s[l] == s[r]) l --, r ++ ;
if(res.size() < r - l - 1) res = s.substr(l + 1, r - l - 1);
//枚举字符串长度是偶数的情况
l = i, r = i + 1;
while(l >= 0 && r < s.size() && s[l] == s[r]) l --, r ++ ;
if(res.size() < r - l - 1) res = s.substr(l + 1, r - l - 1);
}
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/2012413/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
10. 正则表达式匹配
class Solution {
public:
bool isMatch(string s, string p) {
int n = s.size(), m = p.size();
s = ' ' + s, p = ' ' + p;
vector<vector<bool>> f(n + 1, vector<bool>(m + 1));
f[0][0] = true;
for(int i = 0; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
{
if(j + 1 <= m && p[j + 1] == '*') continue;
if(i && p[j] != '*')
{
f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.');
}
else if(p[j] == '*')
{
f[i][j] = f[i][j - 2] || i && f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.');
}
}
return f[n][m];
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/2033105/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
11. 盛最多水的容器
正解是单调栈,巧解为双指针
双指针做法:
class Solution {
public:
int maxArea(vector<int>& height) {
int res = 0;
for(int i = 0, j = height.size() - 1; i < j;)
{
res = max(res, min(height[i], height[j]) * (j - i));
if(height[i] > height[j]) j -- ;
else i ++ ;
}
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/2115435/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
15.三数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i ++ )
{
if(i > 0 && nums[i] == nums[i - 1]) continue;
for(int j = i + 1, k = nums.size() - 1; j < k; j ++ )
{
if(j > i + 1 && nums[j] == nums[j - 1]) continue;
while(j < k - 1 && nums[i] + nums[j] + nums[k - 1] >= 0) k -- ;
if(nums[i] + nums[j] + nums[k] == 0)
{
res.push_back({nums[i], nums[j], nums[k]});
}
}
}
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3852675/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
17. 电话号码的字母组合
class Solution {
public:
vector<string> ans;
string strs[10] = {
"", "", "abc", "def",
"ghi", "jkl", "mno",
"pqrs", "tuv", "wxyz",
};
void dfs(string& digits, int u, string path)
{
if(u == digits.size()) ans.push_back(path);
else
{
for(auto c : strs[digits[u] - '0'])
{
dfs(digits, u + 1, path + c);
}
}
}
vector<string> letterCombinations(string digits) {
if(digits.empty()) return ans;
dfs(digits, 0, "");
return ans;
}
};
19. 删除链表的倒数第 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 k) {
//建立一个虚拟头结点,因为头结点可能会被删掉,这样便于操作
auto dummy = new ListNode(-1);
dummy->next = head;
int len = 0; //计算链表长度
for(auto p = dummy; p; p = p->next) len ++ ;
auto p = dummy;
//跳到要删除节点的前一个点,然后p->next = p->next->next;
for(int i = 0; i < len - k - 1; i ++ ) p = p->next;
p->next = p->next->next;
return dummy->next;
}
};
20. 有效的括号
方法一
class Solution {
public:
stack<char> stk;
bool isValid(string s) {
for(auto c : s)
{
if(stk.empty() || c == '(' || c == '[' || c == '{') stk.push(c);
else if(stk.top() == '(' && c == ')') stk.pop();
else if(stk.top() == '[' && c == ']') stk.pop();
else if(stk.top() == '{' && c == '}') stk.pop();
else return false;
}
if(!stk.empty()) return false;
return true;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3856042/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
方法二
class Solution {
public:
stack<char> stk;
bool isValid(string s) {
for(auto c : s)
{
if(c == '(' || c == '[' || c == '{') stk.push(c);
else
{ // 左右括号的ASCII码值相差不超过2
if(stk.size() && abs(stk.top() - c) <= 2) stk.pop();
else return false;
}
}
return stk.empty();
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3856042/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
21. 合并两个有序链表
/**
* 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* mergeTwoLists(ListNode* l1, ListNode* l2) {
auto dummy = new ListNode(-1), tail = dummy;
while(l1 && l2)
{
if(l1->val < l2->val)
{
tail = tail->next = l1;
l1 = l1->next;
}
else
{
tail = tail->next = l2;
l2 = l2->next;
}
}
if(l1) tail->next = l1;
if(l2) tail->next = l2;
return dummy->next;
}
};
22. 括号生成
class Solution {
public:
vector<string> res;
void dfs(int n, int lcnt, int rcnt, string seq)
{
if(lcnt == n && rcnt == n) res.push_back(seq);
else
{
if(lcnt < n) dfs(n, lcnt + 1, rcnt, seq + '(');
if(rcnt < n && lcnt > rcnt) dfs(n, lcnt, rcnt + 1, seq + ')');
}
}
vector<string> generateParenthesis(int n) {
//合法括号序列满足:任意前缀中左括号数量大于等于右括号数量,且左右括号总数相同
dfs(n, 0, 0, "");
return res;
}
};
23. 合并K个升序链表
/**
* 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:
struct Cmp // 比较函数
{
bool operator() (ListNode* a, ListNode* b)
{
return a->val > b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, Cmp> heap;
auto dummy = new ListNode(-1), tail = dummy;
for(auto l : lists) if(l) heap.push(l);
//用堆来维护k个指针
while(heap.size())
{
auto t = heap.top();
heap.pop();
// 将当前节点插入到尾结点的后面,然后更新当前节点为尾结点
tail = tail->next = t;
if(t->next) heap.push(t->next);
}
return dummy->next;
}
};
31. 下一个排列
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int k = nums.size() - 1; // k为最后一个数的下标(下标从0开始)
//从后往前找,找到第一个逆序的位置
while(k > 0 && nums[k - 1] >= nums[k]) k -- ;
//停下来后,nums[k]是从后往前第一个逆序对中较大的数
if(k <= 0) //整个序列逆序,直接翻转
{
reverse(nums.begin(), nums.end());
}
else
{
int t = k;
while(t < nums.size() && nums[t] > nums[k - 1]) t ++ ;
//nums[k - 1]要与nums[k]后面大于等于nums[k - 1]的最小的数交换
swap(nums[t - 1], nums[k - 1]);
reverse(nums.begin() + k, nums.end());
}
}
};
32. 最长有效括号
合法括号满足两个条件:
1.任意前缀中左括号数量大于等于右括号数量
2.左右括号数量相等
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> stk;
int res = 0;
for(int i = 0, start = -1; i < s.size(); i ++ )
{
if(s[i] == '(') stk.push(i);
else //右括号
{
if(stk.size()) // 栈不空
{
stk.pop(); // 当前右括号与栈顶左括号匹配,弹出栈顶左括号
if(stk.size()) // 如果栈不空
{
res = max(res, i - stk.top());
}
else
{
// 弹出栈顶后栈为空,则长度为start+1到末尾i的长度
res = max(res, i - (start + 1) + 1);
}
}
else // 栈空
{
//说明当前右括号是分界点,更新start
start = i;
}
}
}
return res;
}
};
33. 搜索旋转排序数组
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.empty()) return -1;
int l = 0, r = nums.size() - 1;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(nums[mid] >= nums[0]) l = mid;
else r = mid - 1;
}
if(target >= nums[0]) l = 0;
else l = r + 1, r = nums.size() - 1;
while(l < r)
{
int mid = l + r >> 1;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
if(target == nums[r]) return r;
return -1;
}
};
34. 在排序数组中查找元素的第一个和最后一个位置
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.empty()) return {-1, -1};
int l = 0, r = nums.size() - 1;
while(l < r)
{
int mid = l + r >> 1;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
if(nums[r] != target) return {-1, -1};
int L = r;
l = r, r = nums.size() - 1;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(nums[mid] <= target) l = mid;
else r = mid - 1;
}
return {L, r};
}
};
39. 组合总和
class Solution {
public:
vector<int> path;
vector<vector<int>> res;
void dfs(vector<int>& c, int u, int target)
{
if(target == 0)
{
res.push_back(path);
return;
}
if(u == c.size()) return;
for(int i = 0; c[u] * i <= target; i ++ )
{
dfs(c, u + 1, target - c[u] * i);
path.push_back(c[u]);
}
for(int i = 0; c[u] * i <= target; i ++ )
{
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& c, int target) {
dfs(c, 0, target);
return res;
}
};
42. 接雨水
const int N = 2e4 + 10;
int q[N];
class Solution {
public:
int trap(vector<int>& h) {
int tt = -1;
int res = 0;
for(int i = 0; i < h.size(); i ++ )
{
int last = 0;
while(tt >= 0 && h[q[tt]] <= h[i])
{
res += (h[q[tt]] - last) * (i - q[tt] - 1);
last = h[q[tt]];
tt -- ;
}
if(tt >= 0) res += (h[i] - last) * (i - q[tt] - 1);
q[++ tt] = i;
}
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3231169/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
46. 全排列
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<bool> st;
void dfs(vector<int>& nums, int u)
{
if(u == nums.size())
{
res.push_back(path);
return;
}
for(int i = 0; i < nums.size(); i ++ )
{
if(!st[i])
{
st[i] = true;
path[u] = nums[i];
dfs(nums, u + 1);
st[i] = false;
}
}
}
vector<vector<int>> permute(vector<int>& nums) {
path = vector<int>(nums.size());
st = vector<bool>(nums.size());
dfs(nums, 0);
return res;
}
};
48. 旋转图像
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
//按对角线翻转
for(int i = 0; i < n; i ++ )
for(int j = 0; j < i; j ++ )
swap(matrix[i][j], matrix[j][i]);
//左右翻转
for(int i = 0; i < n; i ++ )
for(int j = 0, k = n - 1; j < k; j ++, k -- )
swap(matrix[i][j], matrix[i][k]);
}
};
49. 字母异位词分组
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
//只需要把每个单词排序一下,两个单词如果排序之后得到的字符串相同
//则说明是字母异位词
unordered_map<string, vector<string>> hash;
for(auto& str : strs)
{
string s = str;
sort(s.begin(), s.end());
hash[s].push_back(str);
}
vector<vector<string>> res;
for(auto& it : hash) res.push_back(it.second);
return res;
}
};
53. 最大子数组和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int res = INT_MIN;
for(int i = 0, last = 0; i < nums.size(); i ++ )
{
last = nums[i] + max(last, 0);
res = max(res, last);
}
return res;
}
};
55. 跳跃游戏
class Solution {
public:
bool canJump(vector<int>& nums) {
for(int i = 0, j = 0; i < nums.size(); i ++ )
{
if(j < i) return false;
j = max(j, i + nums[i]);
}
return true;
}
};
56. 合并区间
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& a) {
vector<vector<int>> res;
if(a.empty()) return res;
sort(a.begin(), a.end());
int l = a[0][0], r = a[0][1];
for(int i = 1; i < a.size(); i ++ )
{
if(r < a[i][0])
{
res.push_back({l, r});
l = a[i][0], r = a[i][1];
}
else if(r < a[i][1]) r = a[i][1];
}
res.push_back({l, r});
return res;
}
};
62. 不同路径
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> f(m, vector<int>(n));
for(int i = 0; i < m; i ++ )
for(int j = 0; j < n; j ++ )
{
if(!i && !j) f[i][j] = 1;
else
{
if(i) f[i][j] += f[i - 1][j];
if(j) f[i][j] += f[i][j - 1];
}
}
return f[m - 1][n - 1];
}
};
64. 最小路径和
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int n = grid.size();
if(!n) return 0;
int m = grid[0].size();
vector<vector<int>> f(n, vector<int>(m, INT_MAX));
for(int i = 0; i < n; i ++ )
for(int j = 0; j < m; j ++ )
{
if(!i && !j) f[i][j] = grid[i][j];
else
{
if(i) f[i][j] = min(f[i][j], f[i - 1][j] + grid[i][j]);
if(j) f[i][j] = min(f[i][j], f[i][j - 1] + grid[i][j]);
}
}
return f[n - 1][m - 1];
}
};
70. 爬楼梯
求斐波那契数列第n项
class Solution {
public:
int climbStairs(int n) {
int a = 1, b = 1;
while(-- n)
{
int c = a + b;
a = b, b = c;
}
return b;
}
};
72. 编辑距离
class Solution {
public:
int minDistance(string a, string b) {
int n = a.size(), m = b.size();
a = ' ' + a, b = ' ' + b;
vector<vector<int>> f(n + 1, vector<int>(m + 1, 1e9));
for(int i = 0; i <= n; i ++ ) f[i][0] = i;
for(int i = 0; i <= m; i ++ ) f[0][i] = i;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
{
f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;
int t = a[i] != b[j];
f[i][j] = min(f[i][j], f[i - 1][j - 1] + t);
}
return f[n][m];
}
};
75. 颜色分类
法一:荷兰国旗问题
固定套路,背会即可。
class Solution {
public:
void sortColors(vector<int>& nums) {
for(int i = 0, j = 0, k = nums.size() - 1; i <= k;)
{
if(nums[i] == 0) swap(nums[i ++ ], nums[j ++ ]);
else if(nums[i] == 2) swap(nums[i], nums[k -- ]);
else i ++ ;
}
}
};
法二:快速排序
class Solution {
public:
void quick_sort(vector<int>& q, int l, int r)
{
if(l >= r) return;
int x = q[l + r >> 1], i = l - 1, j = r + 1;
while(i < j)
{
while(q[++ i] < x);
while(q[-- j] > x);
if(i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
void sortColors(vector<int>& nums) {
quick_sort(nums, 0, nums.size() - 1);
}
};
76. 最小覆盖子串
双指针+哈希表
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> hs, ht;
for(auto c : t) ht[c] ++ ;
string res;
int cnt = 0;
for(int i = 0, j = 0; i < s.size(); i ++ )
{
hs[s[i]] ++ ;
if(hs[s[i]] <= ht[s[i]]) cnt ++ ;
while(hs[s[j]] > ht[s[j]]) hs[s[j ++ ]] -- ;
if(cnt == t.size())
{
if(res.empty() || i - j + 1 < res.size())
res = s.substr(j, i - j + 1);
}
}
return res;
}
};
78. 子集
法一:DFS
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void dfs(vector<int>& nums, int u)
{
if(u >= nums.size())
{
res.push_back(path);
return;
}
//不选当前数
dfs(nums, u + 1);
//选当前数
path.push_back(nums[u]);
dfs(nums, u + 1);
path.pop_back();
}
vector<vector<int>> subsets(vector<int>& nums) {
dfs(nums, 0);
return res;
}
};
法二:二进制枚举
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> res;
//二进制枚举,0~(2^n)-1
for(int i = 0; i < 1 << n; i ++ )
{
vector<int> path;
for(int j = 0; j < n; j ++ )
if(i >> j & 1)
path.push_back(nums[j]);
res.push_back(path);
}
return res;
}
};
79. 单词搜索
class Solution {
public:
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
bool dfs(vector<vector<char>>& board, string &word, int u, int x, int y)
{
if(board[x][y] != word[u]) return false;
if(u == word.size() - 1) return true;
char t = board[x][y];
board[x][y] = '.';
for(int i = 0; i < 4; i ++ )
{
int a = x + dx[i], b = y + dy[i];
if(a < 0 || a >= board.size() || b < 0 || b >= board[0].size() || board[a][b] == '.') continue;
if(dfs(board, word, u + 1, a, b)) return true;
}
board[x][y] = t; //恢复现场,第一次忘了
return false;
}
bool exist(vector<vector<char>>& board, string word) {
int n = board.size();
for(int i = 0; i < n; i ++ )
for(int j = 0; j < board[i].size(); j ++ )
if(dfs(board, word, 0, i, j))
return true;
return false;
}
};
84. 柱状图中最大的矩形
单调栈
class Solution {
public:
int largestRectangleArea(vector<int>& h) {
int n = h.size();
vector<int> l(n), r(n);
stack<int> stk;
for(int i = 0; i < n; i ++ )
{
while(stk.size() && h[stk.top()] >= h[i]) stk.pop();
if(stk.size() == 0) l[i] = -1;
else l[i] = stk.top();
stk.push(i);
}
stk = stack<int>();
for(int i = n - 1; i >= 0; i -- )
{
while(stk.size() && h[stk.top()] >= h[i]) stk.pop();
if(stk.size() == 0) r[i] = n;
else r[i] = stk.top();
stk.push(i);
}
int res = 0;
for(int i = 0; i < n; i ++ )
res = max(res, h[i] * (r[i] - l[i] - 1));
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3231358/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
85. 最大矩形
单调栈
class Solution {
public:
int work(vector<int>& h)
{
int n = h.size();
vector<int> l(n), r(n);
stack<int> stk;
for(int i = 0; i < n; i ++ )
{
while(stk.size() && h[stk.top()] >= h[i]) stk.pop();
if(stk.empty()) l[i] = -1;
else l[i] = stk.top();
stk.push(i);
}
stk = stack<int>();
for(int i = n - 1; i >= 0; i -- )
{
while(stk.size() && h[stk.top()] >= h[i]) stk.pop();
if(stk.empty()) r[i] = n;
else r[i] = stk.top();
stk.push(i);
}
int res = 0;
for(int i = 0; i < n; i ++ )
res = max(res, h[i] * (r[i] - l[i] - 1));
return res;
}
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty() || matrix[0].empty()) return 0;
int n = matrix.size(), m = matrix[0].size();
vector<vector<int>> h(n, vector<int>(m)); // 初始化n * m二维矩阵h
for(int i = 0; i < n; i ++ )
for(int j = 0; j < m; j ++ )
if(matrix[i][j] == '1')
if(i) h[i][j] = h[i - 1][j] + 1;
else h[i][j] = 1;
int res = 0;
for(int i = 0; i < n; i ++ ) res = max(res, work(h[i]));
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3232747/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
94. 二叉树的中序遍历
递归写法
/**
* 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<int> res;
void dfs(TreeNode* root)
{
if(!root) return;
dfs(root->left);
res.push_back(root->val);
dfs(root->right);
}
vector<int> inorderTraversal(TreeNode* root) {
dfs(root);
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3201627/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
迭代写法
/**
* 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<int> res;
void dfs(TreeNode* root)
{
if(!root) return;
dfs(root->left);
res.push_back(root->val);
dfs(root->right);
}
vector<int> inorderTraversal(TreeNode* root) {
dfs(root);
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3201627/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
96. 不同的二叉搜索树
class Solution {
public:
int numTrees(int n) {
vector<int> f(n + 1);
f[0] = 1;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= i; j ++ )
f[i] += f[j - 1] * f[i - j];
return f[n];
}
};
98. 验证二叉搜索树
/**
* 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<int> dfs(TreeNode* root)
{
vector<int> res({1, root->val, root->val});
if(root->left)
{
auto t = dfs(root->left);
if(!t[0] || t[2] >= root->val) res[0] = 0;
res[2] = max(res[2], t[2]);
res[1] = min(res[1], t[1]);
}
if(root->right)
{
auto t = dfs(root->right);
if(!t[0] || t[1] <= root->val) res[0] = 0;
res[2] = max(res[2], t[2]);
res[1] = min(res[1], t[1]);
}
return res;
}
bool isValidBST(TreeNode* root) {
if(!root) return true;
return dfs(root)[0];
}
};
101. 对称二叉树
/**
* 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:
bool dfs(TreeNode* p, TreeNode *q)
{
if(!p && !q) return true;
if(!p || !q || p->val != q->val) return false;
return dfs(p->left, q->right) && dfs(p->right, q->left);
}
bool isSymmetric(TreeNode* root) {
if(!root) return true;
return dfs(root->left, root->right);
}
};
102. 二叉树的层序遍历
/**
* 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<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode*> q;
if(root) q.push(root);
while(q.size())
{
vector<int> level; // 存每层的节点
int len = q.size(); // len为当前层节点数
while(len -- )
{
auto t = q.front();
q.pop();
level.push_back(t->val);
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
res.push_back(level);
}
return res;
}
};
104. 二叉树的最大深度
/**
* 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 maxDepth(TreeNode* root) {
if(!root) return 0;
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
};
105. 从前序与中序遍历序列构造二叉树
/**
* 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:
unordered_map<int, int> pos;
TreeNode* build(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir)
{
if(pl > pr) return NULL;
auto root = new TreeNode(preorder[pl]);
int k = pos[root->val];
root->left = build(preorder, inorder, pl + 1, pl + 1 + k - 1 - il, il, k - 1);
root->right = build(preorder, inorder, pl + 1 + k - 1 - il + 1, pr, k + 1, ir);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i = 0; i < inorder.size(); i ++ ) pos[inorder[i]] = i;
return build(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
}
};
114. 二叉树展开为链表
/**
* 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 flatten(TreeNode* root) {
while(root)
{
auto p = root->left;
if(p)
{
while(p->right) p = p->right;
p->right = root->right;
root->right = root->left;
root->left = NULL;
}
root = root->right;
}
}
};
121. 买卖股票的最佳时机
class Solution {
public:
int maxProfit(vector<int>& prices) {
int res = 0;
for(int i = 0, minv = 1e9; i < prices.size(); i ++ )
{
res = max(res, prices[i] - minv);
minv = min(minv, prices[i]);
}
return res;
}
};
124. 二叉树中的最大路径和
/**
* 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 res;
int dfs(TreeNode* root)
{
if(!root) return 0;
int left = max(0, dfs(root->left)), right = max(0, dfs(root->right));
res = max(res, root->val + left + right);
return root->val + max(left, right);
}
int maxPathSum(TreeNode* root) {
res = -1e9;
dfs(root);
return res;
}
};
128. 最长连续序列
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> S;
for(auto x : nums) S.insert(x);
int res = 0;
for(auto x : nums)
{
if(S.count(x) && !S.count(x - 1))
{
int y = x;
S.erase(x);
while(S.count(y + 1))
{
y ++ ;
S.erase(y);
}
res = max(res, y - x + 1);
}
}
return res;
}
};
136. 只出现一次的数字
class Solution {
public:
int singleNumber(vector<int>& nums) {
for (int i = 1; i < nums.size(); i ++ )
nums[0] ^= nums[i];
return nums[0];
}
};
139. 单词拆分
写法一:
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
const int P = 131;
typedef unsigned long long ULL;
unordered_set<ULL> S;
for (auto word: wordDict)
{
ULL h = 0;
for (auto& c: word) h = h * P + c;
S.insert(h);
}
int n = s.size();
vector<bool> f(n + 1);
f[n] = true;
for (int i = n - 1; i >= 0; i -- )
{
ULL h = 0;
for (int j = i; j < n; j ++ )
{
h = h * P + s[j];
if (S.count(h) && f[j + 1])
{
f[i] = true;
break;
}
}
}
return f[0];
}
};
写法二:
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
const int P = 131;
typedef unsigned long long ULL;
unordered_set<ULL> S;
for (auto word: wordDict)
{
ULL h = 0;
for (auto& c: word) h = h * P + c;
S.insert(h);
}
int n = s.size();
vector<bool> f(n + 1);
f[0] = true;
s = ' ' + s; // 下标从1
for (int i = 0; i < n; i ++ )
{
if (f[i])
{
ULL h = 0;
for (int j = i + 1; j <= n; j ++ )
{
h = h * P + s[j];
if (S.count(h))
{
f[j] = true;
}
}
}
}
return f[n];
}
};
141. 环形链表
快慢指针
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head || !head->next) return false;
auto s = head, f = head->next;
while(f)
{
s = s->next, f = f->next;
if(!f) return false;
f = f->next;
if(f == s) return true;
}
return false;
}
};
142. 环形链表 II
/**
* 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) {
if(!head || !head->next) return NULL;
auto s = head, f = head;
while(f)
{
s = s->next;
f = f->next;
if(!f) return NULL;
f = f->next;
if(s == f)
{
s = head;
while(s != f)
{
s = s->next;
f = f->next;
}
return s;
}
}
return NULL;
}
};
146. LRU 缓存
双链表+哈希表
class LRUCache {
public:
struct Node
{
int key, val;
Node *left, *right;
Node(int _key, int _val): key(_key), val(_val), left(NULL), right(NULL) {}
}*L, *R;
unordered_map<int, Node*> hash;
int n;
LRUCache(int capacity) {
n = capacity;
L = new Node(-1, -1), R = new Node(-1, -1);
L->right = R;
R->left = L;
}
void remove(Node* p)
{
p->left->right = p->right;
p->right->left = p->left;
}
void insert(Node* p)
{
p->right = L->right;
p->left = L;
L->right->left = p;
L->right = p;
}
int get(int key) {
if(hash.count(key) == 0) return -1;
auto p = hash[key];
remove(p);
insert(p);
return p->val;
}
void put(int key, int value) {
if(hash.count(key))
{
auto p = hash[key];
p->val = value;
remove(p);
insert(p);
}
else
{
if(hash.size() == n)
{
auto p = R->left;
remove(p);
hash.erase(p->key);
delete p;
}
auto p = new Node(key, value);
hash[key] = p;
insert(p);
}
}
};
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/
148. 排序链表
/**
* 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* sortList(ListNode* head) {
int n = 0;
for (auto p = head; p; p = p->next) n ++ ;
auto dummy = new ListNode(-1);
dummy->next = head;
for (int i = 1; i < n; i *= 2) {
auto cur = dummy;
for (int j = 1; j + i <= n; j += i * 2) {
auto p = cur->next, q = p;
for (int k = 0; k < i; k ++ ) q = q->next;
int x = 0, y = 0;
while (x < i && y < i && p && q) {
if (p->val <= q->val) cur = cur->next = p, p = p->next, x ++ ;
else cur = cur->next = q, q = q->next, y ++ ;
}
while (x < i && p) cur = cur->next = p, p = p->next, x ++ ;
while (y < i && q) cur = cur->next = q, q = q->next, y ++ ;
cur->next = q;
}
}
return dummy->next;
}
};
152. 乘积最大子数组
class Solution {
public:
int maxProduct(vector<int>& nums) {
int res = nums[0];
int f = nums[0], g = nums[0];
for (int i = 1; i < nums.size(); i ++ )
{
int a = nums[i], fa = f * a, ga = g * a;
f = max(a, max(fa, ga));
g = min(a, min(fa, ga));
res = max(res, f);
}
return res;
}
};
155. 最小栈
class MinStack {
public:
stack<int> stk;
stack<int> stk_min;
MinStack() {
}
void push(int val) {
stk.push(val);
if (stk_min.size()) {
int x = stk_min.top();
stk_min.push(min(x, val));
} else {
stk_min.push(val);
}
}
void pop() {
stk.pop();
stk_min.pop();
}
int top() {
return stk.top();
}
int getMin() {
return stk_min.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
160. 相交链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
auto p = headA, q = headB;
while(p != q)
{
p = p ? p->next : headB;
q = q ? q->next : headA;
}
return p;
}
};
169. 多数元素(摩尔投票法)
摩尔投票法
class Solution {
public:
int majorityElement(vector<int>& nums) {
int val, cnt = 0;
for(auto c : nums)
{
if(cnt == 0) val = c, cnt ++ ;
else if(c == val) cnt ++ ;
else cnt -- ;
}
return val;
}
};
198. 打家劫舍
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
vector<int> f(n + 1), g(n + 1);
for(int i = 1; i <= n; i ++ )
{
f[i] = g[i - 1] + nums[i - 1];
g[i] = max(f[i - 1], g[i - 1]);
}
return max(f[n], g[n]);
}
};
200. 岛屿数量
BFS写法
typedef pair<int, int> PII;
class Solution {
public:
vector<vector<char>> g;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void bfs(int x, int y)
{
g[x][y] = '0';
queue<PII> q;
q.push({x, y});
while(q.size())
{
PII t = q.front();
q.pop();
for(int i = 0; i < 4; i ++ )
{
int a = t.first + dx[i], b = t.second + dy[i];
if(a >= 0 && a < g.size() && b >= 0 && b < g[a].size() && g[a][b] == '1')
{
q.push({a, b});
g[a][b] = '0';
}
}
}
}
int numIslands(vector<vector<char>>& grid) {
g = grid;
int res = 0;
for(int i = 0; i < g.size(); i ++ )
for(int j = 0; j < g[0].size(); j ++ )
if(g[i][j] == '1')
{
bfs(i, j);
res ++ ;
}
return res;
}
};
DFS写法
class Solution {
public:
vector<vector<char>> g;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void dfs(int x, int y)
{
g[x][y] = '0';
for(int i = 0; i < 4; i ++ )
{
int a = x + dx[i], b = y + dy[i];
if(a >= 0 && a < g.size() && b >= 0 && b < g[a].size() && g[a][b] == '1')
dfs(a, b);
}
}
int numIslands(vector<vector<char>>& grid) {
g = grid;
int res = 0;
for(int i = 0; i < g.size(); i ++ )
for(int j = 0; j < g[0].size(); j ++ )
if(g[i][j] == '1')
{
dfs(i, j);
res ++ ;
}
return res;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/4095528/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
206. 反转链表
迭代做法
/**
* 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 || !head->next) return head; // 如果是空节点或只有一个结点,直接返回
auto a = head, b = a->next;
while(b)
{
auto c = b->next;
b->next = a;
a = b, b = c;
}
head->next = NULL;
return a; //此时a为原来的尾结点,即反转链表后的新结点
}
};
递归做法
/**
* 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 || !head->next) return head;
auto tail = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return tail;
}
};
207. 课程表
拓扑排序
class Solution {
public:
bool canFinish(int n, vector<vector<int>>& edges) {
vector<vector<int>> g(n);
vector<int> d(n);
for(auto& e : edges)
{
int b = e[0], a = e[1];
g[a].push_back(b);
d[b] ++ ;
}
queue<int> q;
for(int i = 0; i < n; i ++ )
if(!d[i])
q.push(i);
int cnt = 0;
while(q.size())
{
int t = q.front();
q.pop();
cnt ++ ;
for(auto j : g[t])
{
if(-- d[j] == 0)
q.push(j);
}
}
return cnt == n;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3062261/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
208. 实现 Trie (前缀树)
class Trie {
public:
struct Node
{
Node* son[26];
bool is_end;
Node()
{
for(int i = 0; i < 26; i ++ ) son[i] = NULL;
is_end = false;
}
}*root;
Trie() {
root = new Node();
}
void insert(string word) {
auto p = root;
for(auto c : word)
{
int u = c - 'a';
if(!p->son[u]) p->son[u] = new Node();
p = p->son[u];
}
p->is_end = true;
}
bool search(string word) {
auto p = root;
for(auto c : word)
{
int u = c - 'a';
if(!p->son[u]) return false;
p = p->son[u];
}
return p->is_end;
}
bool startsWith(string prefix) {
auto p = root;
for(auto c : prefix)
{
int u = c - 'a';
if(!p->son[u]) return false;
p = p->son[u];
}
return true;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/3337748/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
215. 数组中的第K个最大元素
快速选择排序
class Solution {
public:
int quick_sort(vector<int>& q, int l, int r, int k)
{
if(l == r) return q[k];
int i = l - 1, j = r + 1, x = q[l + r >> 1];
while(i < j)
{
while(q[++ i] > x); //求第k大元素,这里要写大于号,与快排相反
while(q[-- j] < x); //写小于号,与快排相反
if(i < j) swap(q[i], q[j]);
}
if(k <= j) return quick_sort(q, l, j, k);
return quick_sort(q, j + 1, r, k);
}
int findKthLargest(vector<int>& nums, int k) {
return quick_sort(nums, 0, nums.size() - 1, k - 1);
}
};
221. 最大正方形
图片来源于题解:LeetCode 221. 最大正方形
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
if(matrix.empty() || matrix[0].empty()) return 0;
int n = matrix.size(), m = matrix[0].size();
vector<vector<int>> f(n + 1, vector<int>(m + 1));
int res = 0;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
if(matrix[i - 1][j - 1] == '1')
{
f[i][j] = min(f[i - 1][j], min(f[i - 1][j - 1], f[i][j - 1])) + 1;
res = max(res, f[i][j]);
}
return res * res;
}
};
226. 翻转二叉树
将左右子树对调,然后再递归地翻转左右子树本身
/**
* 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:
TreeNode* invertTree(TreeNode* root) {
if(!root) return NULL;
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
234. 回文链表
/**
* 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:
bool isPalindrome(ListNode* head) {
vector<int> q;
for(auto p = head; p; p = p->next) q.push_back(p->val);
for(int i = 0, j = q.size() - 1; i < j, j >= 0; i ++, j -- )
{
if(q[i] != q[j])
return false;
}
return true;
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/4105150/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
236. 二叉树的最近公共祖先
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* res = NULL;
int dfs(TreeNode* root, TreeNode* p, TreeNode* q)
{
if(!root) return 0;
int state = dfs(root->left, p, q);
if(root == p) state |= 1;
else if(root == q) state |= 2;
state |= dfs(root->right, p, q);
if(state == 3 && !res) res = root;
return state;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
dfs(root, p, q);
return res;
}
};
238. 除自身以外数组的乘积
在acwing题库上搜前后缀分解
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> p(n, 1); // 初始化为n个值为1的int
for(int i = 1; i < n; i ++ ) p[i] = p[i - 1] * nums[i - 1];
for(int i = n - 1, s = 1; i >= 0; i -- )
{
p[i] *= s;
s *= nums[i];
}
return p;
}
};
239. 滑动窗口最大值
单调队列
class Solution {
public:
vector<int> res;
deque<int> q;
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
for(int i = 0; i < nums.size(); i ++ )
{
if(q.size() && i - k + 1 > q.front()) 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;
}
};
240. 搜索二维矩阵 II
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.empty() || matrix[0].empty()) return false;
int n = matrix.size(), m = matrix[0].size();
int i = 0, j = m - 1;
while(i < n && j >= 0)
{
int t = matrix[i][j];
if(t == target) return true;
else if(t > target) j -- ;
else i ++ ;
}
return false;
}
};
279. 完全平方数
勒让德三平方和定理、拉格朗日四平方和定理
由拉格朗日四平方和定理知,答案只能为1,2,3,4,挨个判断每个情况
class Solution {
public:
bool check(int x)
{
int r = sqrt(x);
return r * r == x;
}
int numSquares(int n) {
// 判断1的情况
if(check(n)) return 1;
// 判断2的情况
for(int a = 1; a <= n / a; a ++ )
if(check(n - a * a))
return 2;
//判断3
while(n % 4 == 0) n /= 4;
if(n % 8 != 7) return 3;
//以上三种情况都不是,则为4
return 4;
}
};
283. 移动零
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k = 0;
for(auto x : nums)
{
if(x)
nums[k ++ ] = x;
}
while(k < nums.size()) nums[k ++ ] = 0;
}
};
287. 寻找重复数
本题可以转化为142. 环形链表 II
相当于在链表中找环的入口
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int a = 0, b = 0;
while(true)
{
a = nums[a];
b = nums[nums[b]];
if(a == b)
{
a = 0;
while(a != b)
{
a = nums[a];
b = nums[b];
}
return a;
}
}
return -1;
}
};
297. 二叉树的序列化与反序列化
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
string path;
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
dfs_s(root);
return path;
}
void dfs_s(TreeNode* root) {
if (!root) {
path += "#,";
} else {
path += to_string(root->val) + ',';
dfs_s(root->left);
dfs_s(root->right);
}
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int u = 0;
return dfs_d(data, u);
}
TreeNode* dfs_d(string& data, int& u) {
if (data[u] == '#') {
u += 2;
return NULL;
} else {
int k = u;
while (data[u] != ',') u ++ ;
auto root = new TreeNode(stoi(data.substr(k, u - k)));
u ++ ;
root->left = dfs_d(data, u);
root->right = dfs_d(data, u);
return root;
}
}
};
// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
300. 最长递增子序列
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> q;
for(auto x : nums)
{
if(q.empty() || x > q.back()) q.push_back(x);
else
{
if(x <= q[0]) q[0] = x;
else
{
int l = 0, r = q.size() - 1;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(q[mid] < x) l = mid;
else r = mid - 1;
}
q[r + 1] = x;
}
}
}
return q.size();
}
};
作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/2380007/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
301. 删除无效的括号
class Solution {
public:
vector<string> res;
/*
合法括号序列性质:
1.左右括号数量相等
2.任意前缀中左括号数量>=右括号数量
*/
vector<string> removeInvalidParentheses(string s) {
int l = 0, r = 0; //l表示左括号数量-右括号数量, r表示当前要删掉多少个右括号
for (auto x: s) {
if (x == '(') l ++ ;
else if (x == ')') {
if (l == 0) r ++ ; // 左右括号数量相同,把右括号删掉,删掉右括号的数量++
else l -- ; // (left - right) - 1
}
}
dfs(s, 0, "", 0, l, r); // l 为要删掉左括号数量,r表示要删掉右括号的数量
return res;
}
//cnt 表示左括号数量-右括号数量, l为当前可以删掉的左括号数量,r为当前可以删掉的右括号数量
void dfs(string& s, int u, string path, int cnt, int l, int r) {
if (u == s.size()) {
if (!cnt) res.push_back(path);
return;
}
if (s[u] != '(' && s[u] != ')') {
dfs(s, u + 1, path + s[u], cnt, l, r);
} else if (s[u] == '(') {
int k = u;
while (k < s.size() && s[k] == '(') k ++ ;
l -= k - u;
for (int i = k - u; i >= 0; i -- ) {
if (l >= 0) dfs(s, k, path, cnt, l, r);
path += '(';
cnt ++, l ++ ;
}
} else if (s[u] == ')') {
int k = u;
while (k < s.size() && s[k] == ')') k ++ ;
r -= k - u;
for (int i = k - u; i >= 0; i -- ) {
if(cnt >= 0 && r >= 0) dfs(s, k, path, cnt, l, r);
path += ')';
cnt --, r ++ ;
}
}
}
};
309. 最佳买卖股票时机含冷冻期
状态机DP
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty()) return 0;
int n = prices.size(), INF = 1e9;
vector<vector<int>> f(n, vector<int>(3, -INF));
f[0][1] = -prices[0], f[0][0] = 0;
for (int i = 1; i < n; i ++ ) {
f[i][0] = max(f[i - 1][0], f[i - 1][2]);
f[i][1] = max(f[i - 1][0] - prices[i], f[i - 1][1]);
f[i][2] = f[i - 1][1] + prices[i];
}
return max(f[n - 1][0], max(f[n - 1][1], f[n - 1][2]));
}
};
312. 戳气球
区间DP
class Solution {
public:
int maxCoins(vector<int>& nums) {
int n = nums.size();
vector<int> a(n + 2, 1);
for (int i = 1; i <= n; i ++ ) a[i] = nums[i - 1];
vector<vector<int>> f(n + 2, vector<int>(n + 2));
for (int len = 3; len <= n + 2; len ++ ) {
for (int i = 0; i + len - 1 <= n + 1; i ++ ) {
int j = i + len - 1;
for (int k = i + 1; k < j; k ++ ) {
f[i][j] = max(f[i][j], f[i][k] + f[k][j] + a[i] * a[k] * a[j]);
}
}
}
return f[0][n + 1];
}
};
322. 零钱兑换
完全背包问题
class Solution {
public:
int coinChange(vector<int>& coins, int m) {
vector<int> f(m + 1, 1e8);
f[0] = 0;
for (auto v: coins)
for (int j = v; j <= m; j ++ )
f[j] = min(f[j], f[j - v] + 1);
if (f[m] == 1e8) return -1;
return f[m];
}
};
337. 打家劫舍 III
树形DP
/**
* 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 rob(TreeNode* root) {
auto f = dfs(root);
return max(f[0], f[1]);
}
vector<int> dfs(TreeNode* root) {
if (!root) return {0, 0};
auto x = dfs(root->left), y = dfs(root->right);
return {max(x[0], x[1]) + max(y[0], y[1]), x[0] + y[0] + root->val};
}
};
338. 比特位计数
class Solution {
public:
vector<int> countBits(int n) {
vector<int> f(n + 1);
// 递推,i >> 1表示除了最后一位之外1的个数
for (int i = 1; i <= n; i ++ )
f[i] = f[i >> 1] + (i & 1);
return f;
}
};
347. 前 K 个高频元素
计数排序
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> cnt;
for (auto x: nums) cnt[x] ++ ;
int n = nums.size();
vector<int> s(n + 1);
for (auto it: cnt) s[it.second] ++ ;
int i = n, t = 0;
while (t < k) t += s[i -- ];
vector<int> res;
for (auto it: cnt)
if (it.second > i)
res.push_back(it.first);
return res;
}
};
394. 字符串解码
class Solution {
public:
string decodeString(string s) {
int u = 0;
return dfs(s, u);
}
string dfs(string& s, int& u) {
string res;
while (u < s.size() && s[u] != ']') {
if (isalpha(s[u])) {
res += s[u ++ ];
} else if (isdigit(s[u])) {
int k = u;
while (isdigit(s[k])) k ++ ;
int x = stoi(s.substr(u, k - u));
u = k + 1;
string y = dfs(s, u);
u ++ ; //过滤右括号
while (x -- ) res += y;
}
}
return res;
}
};
399. 除法求值
class Solution {
public:
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
unordered_set<string> vers;
unordered_map<string, unordered_map<string, double>> d;
for (int i = 0; i < equations.size(); i ++ ) {
auto a = equations[i][0], b = equations[i][1];
auto c = values[i];
d[a][b] = c;
d[b][a] = 1 / c;
vers.insert(a);
vers.insert(b);
}
//弗洛伊德算法
for (auto k: vers)
for (auto i: vers)
for (auto j: vers)
if (d[i][k] && d[j][k])
d[i][j] = d[i][k] * d[k][j];
vector<double> res;
for (auto q: queries) {
auto a = q[0], b = q[1];
if (d[a][b]) res.push_back(d[a][b]);
else res.push_back(-1);
}
return res;
}
};
406. 根据身高重建队列
贪心思想 (二分+树状数组优化)
class Solution {
public:
int n;
vector<int> tr;
int lowbit(int x) {
return x & -x;
}
void add(int x, int c) {
for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
int query(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
n = people.size();
tr.resize(n + 1);
sort(people.begin(), people.end(), [](vector<int>& a, vector<int>& b) {
if (a[0] != b[0]) return a[0] < b[0];
return a[1] > b[1];
});
vector<vector<int>> res(n);
for (auto p : people) {
int h = p[0], k = p[1];
int l = 1, r = n;
while (l < r) {
int mid = l + r >> 1;
if (mid - query(mid) >= k + 1) r = mid;
else l = mid + 1;
}
res[r - 1] = p;
add(r, 1);
}
return res;
}
};
416. 分割等和子集
01背包问题
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size(), sum = 0;
for (auto x: nums) sum += x;
if (sum % 2) return false;
sum /= 2;
vector<int> f(sum + 1);
f[0] = 1;
for (auto i: nums)
for (int j = sum; j >= i; j -- )
f[j] |= f[j - i];
return f[sum];
}
};
437. 路径总和 III
/**
* 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:
unordered_map<long long, long long> cnt;
long long res = 0;
long long pathSum(TreeNode* root, int target) {
cnt[0] = 1;
dfs(root, target, 0);
return res;
}
void dfs(TreeNode* root, int target, long long cur) {
if (!root) return;
cur += root->val;
res += cnt[cur - target];
cnt[cur] ++ ;
dfs(root->left, target, cur);
dfs(root->right, target, cur);
cnt[cur] -- ;
}
};
438. 找到字符串中所有字母异位词
双指针维护滑动窗口
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
unordered_map<char, int> hash;
for(auto c : p) hash[c] ++ ;
vector<int> res;
int tot = hash.size();
for(int i = 0, j = 0, satisify = 0; i < s.size(); i ++ )
{
if(-- hash[s[i]] == 0) satisify ++ ;
while(i - j + 1 > p.size())
{
if(hash[s[j]] == 0) satisify -- ;
hash[s[j ++ ]] ++ ;
}
if(satisify == tot) res.push_back(j);
}
return res;
}
};
写法二:
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int cnt[26] = {0};
int a = 0, b = 0;
for(auto c : p) cnt[c - 'a'] ++ ;
for(int i = 0; i < 26; i ++ ) if(cnt[i] != 0) a ++ ;
vector<int> res;
for(int l = 0, r = 0; r < s.size(); r ++ )
{
if(-- cnt[s[r] - 'a'] == 0) b ++ ;
if(r - l + 1 > p.size() && ++ cnt[s[l ++ ] - 'a'] == 1) b -- ;
if(a == b) res.push_back(l);
}
return res;
}
};
448. 找到所有数组中消失的数字
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
for (auto x: nums) {
x = abs(x);
if (nums[x - 1] > 0) nums[x - 1] *= -1;
}
vector<int> res;
for (int i = 0; i < nums.size(); i ++ ) {
if (nums[i] > 0)
res.push_back(i + 1);
}
return res;
}
};
494. 目标和
class Solution {
public:
int findTargetSumWays(vector<int>& a, int target) {
if (target < -1000 || target > 1000) return 0;
int n = a.size(), offset = 1000;
vector<vector<int>> f(n + 1, vector<int>(2001));
f[0][0 + offset] = 1;
for (int i = 1; i <= n; i ++ )
for (int j = -1000; j <= 1000; j ++ ) {
if (j - a[i - 1] >= -1000)
f[i][j + offset] += f[i - 1][j - a[i - 1] + offset];
if (j + a[i - 1] <= 1000)
f[i][j + offset] += f[i - 1][j + a[i - 1] + offset];
}
return f[n][target + offset];
}
};
538. 把二叉搜索树转换为累加树
/**
* 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 sum = 0;
TreeNode* convertBST(TreeNode* root) {
dfs(root);
return root;
}
void dfs(TreeNode* root) {
if (!root) return;
dfs(root->right);
int x = root->val;
root->val += sum;
sum += x;
dfs(root->left);
}
};
543. 二叉树的直径
/**
* 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 res = 0;
int diameterOfBinaryTree(TreeNode* root) {
dfs(root);
return res;
}
int dfs(TreeNode* root) {
if (!root) return 0;
int left = dfs(root->left);
int right = dfs(root->right);
res = max(res, left + right);
return max(left, right) + 1;
}
};
560. 和为 K 的子数组
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int n = nums.size();
vector<int> s(n + 1);
for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + nums[i - 1];
unordered_map<int, int> hash;
hash[0] = 1;
int res = 0;
for (int i = 1; i <= n; i ++ ) {
res += hash[s[i] - k];
hash[s[i]] ++ ;
}
return res;
}
};
581. 最短无序连续子数组
class Solution {
public:
int findUnsortedSubarray(vector<int>& nums) {
int l = 0, r = nums.size() - 1;
while (l + 1 < nums.size() && nums[l + 1] >= nums[l]) l ++ ;
if (l == r) return 0;
while (r - 1 >= 0 && nums[r - 1] <= nums[r]) r -- ;
for (int i = l + 1; i < nums.size(); i ++ )
while (l >= 0 && nums[l] > nums[i])
l -- ;
for (int i = r - 1; i >= 0; i -- )
while (r < nums.size() && nums[r] < nums[i])
r ++ ;
return r - l - 1;
}
};
617. 合并二叉树
/**
* 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:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if (root2) swap(root1, root2);
if (!root1) return NULL;
root1->left = mergeTrees(root1->left, root2 ? root2->left : NULL);
root1->right = mergeTrees(root1->right, root2 ? root2->right : NULL);
if (root2) root1->val += root2->val;
return root1;
}
};
621. 任务调度器
class Solution {
public:
int leastInterval(vector<char>& tasks, int n) {
unordered_map<char, int> hash;
for (auto c: tasks) hash[c] ++ ;
int maxc = 0, cnt = 0;
for (auto it: hash) maxc = max(maxc, it.second); //maxc为出现次数最多的数的个数
for (auto it: hash)
if (maxc == it.second)
cnt ++ ;
return max((int)tasks.size(), (maxc - 1) * (n + 1) + cnt);
}
};
647. 回文子串
class Solution {
public:
int countSubstrings(string s) {
int res = 0;
for(int i = 0; i < s.size(); i ++ )
{
//枚举回文串长度为奇数的情况
for(int j = i, k = i; j >= 0 && k < s.size(); j --, k ++ )
{
if(s[j] != s[k]) break;
res ++ ;
}
//枚举回文串长度为偶数的情况
for(int j = i, k = i + 1; j >= 0 && k < s.size(); j --, k ++ )
{
if(s[j] != s[k]) break;
res ++ ;
}
}
return res;
}
};
739. 每日温度
单调栈
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& t) {
vector<int> res(t.size());
stack<int> stk;
for (int i = t.size() - 1; i >= 0; i -- ) {
while (stk.size() && t[i] >= t[stk.top()]) stk.pop();
if (stk.size()) res[i] = stk.top() - i;
stk.push(i);
}
return res;
}
};
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程