classSolution{
public:intlongestConsecutive(vector<int>& nums){
if(nums.size()==0)return0;
unordered_set<int> ust;for(auto x : nums) ust.insert(x);int res =0;for(auto x : ust){
if(!ust.count(x -1)){
int y = x;while(ust.count(y)){
y++;// 这里不能对y进行删除,因为外层循环正在对ust进行遍历}
res =max(res, y - x);}}return res;}};
283. 移动零(Easy,双指针)
classSolution{
public:voidmoveZeroes(vector<int>& nums){
int k =0;for(int i =0; i < nums.size(); i++){
if(nums[i]!=0)swap(nums[i], nums[k++]);// 保证指针k的左边一定都是非零数}}};
11. 盛最多水的容器(Medium,贪心(用双指针实现))
classSolution{
public:intmaxArea(vector<int>& height){
int res =0;int lo =0, hi = height.size()-1;while(lo < hi){
res =max(res,(hi - lo)*min(height[lo], height[hi]));if(height[lo]< height[hi]) lo++;else hi--;}return res;}};
15. 三数之和(Medium,双指针)
classSolution{
public:
vector<vector<int>>threeSum(vector<int>& nums){
sort(nums.begin(), nums.end());
vector<vector<int>> res;int n = nums.size();for(int i =0; i < n; i++){
if(i && nums[i]== nums[i -1])continue;int lo = i +1, hi = n -1;while(lo < hi){
while(lo < hi && lo > i +1&& nums[lo]== nums[lo -1]) lo++;while(lo < hi && hi < n -1&& nums[hi]== nums[hi +1]) hi--;if(lo < hi){
int sum = nums[i]+ nums[lo]+ nums[hi];if(sum ==0){
res.push_back({
nums[i], nums[lo], nums[hi]});
lo++, hi--;}elseif(sum >0) hi--;else lo++;}}}return res;}};
42. 接雨水(Hard,贪心(用双指针实现))
classSolution{
public:inttrap(vector<int>& height){
int res =0;int leftMaxH =0, rightMaxH =0;int lo =0, hi = height.size()-1;while(lo < hi){
leftMaxH =max(leftMaxH, height[lo]);
rightMaxH =max(rightMaxH, height[hi]);if(leftMaxH < rightMaxH){
res += leftMaxH - height[lo];
lo++;}else{
res += rightMaxH - height[hi];
hi--;}}return res;}};
3. 无重复字符的最长子串(Medium,滑动窗)
classSolution{
public:intlengthOfLongestSubstring(string s){
unordered_map<char,int> wind;int res =0;for(int lo =0, hi =0; hi < s.size(); hi++){
wind[s[hi]]++;while(wind[s[hi]]>1) wind[s[lo++]]--;
res =max(res, hi - lo +1);}return res;}};
classSolution{
public:intsubarraySum(vector<int>& nums,int k){
int n = nums.size();
vector<int>s(n +1);for(int i =1; i <= nums.size(); i++)
s[i]= s[i -1]+ nums[i -1];
unordered_map<int,int> ht;
ht[0]=1;int res =0;for(int i =1; i <= n; i++){
res += ht[s[i]- k];
ht[s[i]]++;}return res;}};
239. 滑动窗口最大值(Hard,单调队列(须用双端队列实现))
classSolution{
public:
vector<int>maxSlidingWindow(vector<int>& nums,int k){
deque<int> dq;
vector<int> res;for(int i =0; i < nums.size(); i++){
if(!dq.empty()&& dq.front()< i - k +1)
dq.pop_front();while(!dq.empty()&& nums[dq.back()]< nums[i])
dq.pop_back();
dq.push_back(i);if(i +1>= k) res.push_back(nums[dq.front()]);}return res;}};
76. 最小覆盖子串(Hard,滑动窗)
classSolution{
public:
string minWindow(string s, string t){
unordered_map<char,int> ht;for(auto c : t) ht[c]++;int target = ht.size();
unordered_map<char,int> wind;
string res;int validCnt =0;for(int lo =0, hi =0; hi < s.size(); hi++){
wind[s[hi]]++;if(wind[s[hi]]== ht[s[hi]]) validCnt++;while(wind[s[lo]]> ht[s[lo]]){
// 因为判断条件是wind[s[lo]] > ht[s[lo]],所以validCnt永远不可能减小
wind[s[lo]]--; lo++;}if(validCnt == target){
if(res.empty()|| res.size()> hi - lo +1)
res = s.substr(lo, hi - lo +1);}}return res;}};
53. 最大子数组和(Medium,模板题:DP:连续子数组的最大和)
classSolution{
public:intmaxSubArray(vector<int>& nums){
int res = nums[0];// 记录0~n-1中连续子数组和的最大值int cur = nums[0];// cur表示以nums[i]结尾的连续子数组的最大和for(int i =1; i < nums.size(); i++){
cur =max(cur + nums[i], nums[i]);
res =max(res, cur);}return res;}};// 状态表示:// 集合:dp[i]表示所有以nums[i]结尾的连续子数组构成的集合;// 属性:集合中元素的最大值// 状态转移(集合划分):// 按集合中元素个数是否为1,可划分为两大类:// 第一类:集合中只有一个元素,即nums[i];// 第二类:集合中元素个数大于1,即dp[i - 1] + nums[i];// 由此可得状态转移方程:dp[i] = max(dp[i - 1] + nums[i], nums[i]);
56. 合并区间(Medium,模板题:区间合并)
classSolution{
public:
vector<vector<int>>merge(vector<vector<int>>& intervals){
sort(intervals.begin(), intervals.end(),[](const vector<int>& a,const vector<int>& b){
return a[0]< b[0];});
vector<vector<int>> res;int st =-1, ed =-1;for(auto& t : intervals){
if(ed < t[0]){
if(st !=-1) res.push_back({
st, ed});
st = t[0], ed = t[1];}else ed =max(ed, t[1]);}if(st !=-1) res.push_back({
st, ed});return res;}};
classSolution{
public:
vector<int>productExceptSelf(vector<int>& nums){
int n = nums.size();
vector<int>res(n,1);/* 处理前缀积 */for(int i =1; i < n; i++) res[i]= res[i -1]* nums[i -1];/* 处理后缀积,同时得到整个res数组 */int suffix =1;for(int i = n -2; i >=0; i--){
suffix *= nums[i +1];
res[i]*= suffix;}return res;}};
41. 缺失的第一个正数(Hard,同秩映射)
classSolution{
public:intfirstMissingPositive(vector<int>& nums){
int n = nums.size();for(int i =0; i < n; i++){
while(nums[i]>=1&& nums[i]<= n && nums[nums[i]-1]!= nums[i])swap(nums[nums[i]-1], nums[i]);}for(int i =0; i < n; i++)if(nums[i]!= i +1)return i +1;return n +1;}};// nums[i] = i + 1;// nums[i] - 1 = i;// nums[nums[i] - 1] = nums[i];
73. 矩阵置零(Medium,trick:利用原矩阵的第一行和第一列来存储状态)
classSolution{
public:voidsetZeroes(vector<vector<int>>& matrix){
int n = matrix.size(), m = matrix[0].size();bool firstRowHasZero =false, firstColHasZero =false;for(int j =0; j < m; j++)if(matrix[0][j]==0) firstRowHasZero =true;for(int i =0; i < n; i++)if(matrix[i][0]==0) firstColHasZero =true;for(int i =1; i < n; i++){
for(int j =1; j < m; j++){
if(matrix[i][j]==0){
matrix[i][0]=0;
matrix[0][j]=0;}}}for(int i =1; i < n; i++){
for(int j =1; j < m; j++){
if(matrix[i][0]==0|| matrix[0][j]==0)
matrix[i][j]=0;}}if(firstRowHasZero)for(int j =0; j < m; j++) matrix[0][j]=0;if(firstColHasZero)for(int i =0; i < n; i++) matrix[i][0]=0;}};
54. 螺旋矩阵(Medium,方向数组的应用)
classSolution{
public:
vector<int>spiralOrder(vector<vector<int>>& matrix){
vector<int> dx{
0,1,0,-1}, dy{
1,0,-1,0};
vector<int> res;int x =0, y =-1;int n = matrix.size(), m = matrix[0].size();int dir =0;
vector<vector<bool>>st(n,vector<bool>(m));for(int i =0; i < n * m; i++){
x += dx[dir], y += dy[dir];if(x <0|| x >= n || y <0|| y >= m || st[x][y]){
x -= dx[dir], y -= dy[dir];
dir =(dir +1)%4;
x += dx[dir], y += dy[dir];}
res.push_back(matrix[x][y]);
st[x][y]=true;}return res;}};
classSolution{
public:voidrotate(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; j < n /2; j++){
swap(matrix[i][j], matrix[i][n -1- j]);}}}};
240. 搜索二维矩阵 II(Medium,trick:从右上角开始查找,可使时间复杂度降至 O ( max ( m , n ) ) O(\max (m, n)) O(max(m,n)))
classSolution{
public:boolsearchMatrix(vector<vector<int>>& matrix,int target){
int n = matrix.size(), m = matrix[0].size();int i =0, j = m -1;while(i < n && j >=0){
if(matrix[i][j]== target)returntrue;elseif(matrix[i][j]> target) j--;else i++;}returnfalse;}};