目录
topcode顺序刷题
215. 数组中的第K个最大元素
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> pg;
for(int i = 0; i < nums.size(); i++)
{
pg.push(-nums[i]);
if(pg.size() > k)
{
pg.pop();
}
}
int result = -pg.top();
return result;
}
};
笔记:
优先队列默认是一个最大堆,每次输出的堆顶元素是此时堆中的最大元素。
详解:c++优先队列(priority_queue)用法详解_c++优先级队列_吕白_的博客-CSDN博客
25. K 个一组翻转链表
class Solution {
public:
void reverse(ListNode* head, ListNode* last) {
ListNode* cur = head;
ListNode* pre = nullptr;
ListNode* tmp;
while(pre != last)
{
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* result = new ListNode(0);
ListNode* pre = result;
ListNode* tail = head;
while(head)
{
tail = head;
for(int i = 1; i < k; i++)
{
tail = tail->next;
if(tail == nullptr)
{
pre->next = head;
return result->next;
}
}
ListNode* curtail = tail->next;
reverse(head,tail);
pre->next = tail;
pre = head;
head = curtail;
}
return result->next;
}
};
就是分步,每k个进行一个旋转,主要问题是在旋转的时候设置变量的时候要注意,指针别指错了。
15. 三数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> result;
vector<int> cur;
for(int i = 0; i < nums.size(); i++)
{
if(nums[i] > 0)
break;
if(i > 0 && nums[i] == nums[i-1])
continue;
int j = i+1;
int k = nums.size()-1;
while(j < k)
{
if(nums[i] + nums[j] + nums[k] == 0)
{
cur.clear();
cur.push_back(nums[i]);
cur.push_back(nums[j]);
cur.push_back(nums[k]);
result.push_back(cur);
while(j < k && nums[j+1] == nums[j])
{
j++;
}
while(j < k && nums[k-1] == nums[k])
{
k--;
}
j++;
k--;
}else if(nums[i] + nums[j] + nums[k] > 0)
{
k--;
}else if(nums[i] + nums[j] +nums[k] < 0)
{
j++;
}
}
}
return result;
}
};
搞一个滑动窗口就行
53. 最大子数组和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> dp(nums.size(),0);
dp[0] = nums[0];
int result = nums[0];
if(nums.size() == 1)
return nums[0];
for(int i = 1; i < nums.size(); i++)
{
dp[i] = max(dp[i-1]+nums[i],nums[i]);
if(dp[i] > result)
result = dp[i];
}
return result;
}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* head = new ListNode(0);
head->next = nullptr;
ListNode* result = head;
while(list1&&list2)
{
if(list1->val > list2->val)
{
head->next = list2;
list2 = list2->next;
head = head->next;
}else if(list1 ->val <= list2->val)
{
head->next = list1;
list1 = list1->next;
head = head->next;
}
}
if(list1)
head->next = list1;
if(list2)
head->next = list2;
return result->next;
}
};
1. 两数之和
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
for(int i = 0 ; i < nums.size(); i ++)
{
int curr = target - nums[i];
for(int j = i+1; j < nums.size(); j++)
{
if(nums[j] == curr)
{
result.push_back(i);
result.push_back(j);
}
}
}
return result;
}
};
简单粗暴
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
unordered_map<int,int> unmap;
for(int i = 0 ; i < nums.size(); i++)
{
unmap.insert(pair<int,int>(nums[i],i));
}
for(int i = 0; i < nums.size(); i++)
{
int cur = target - nums[i];
if(unmap.find(cur) != unmap.end())
{
auto index = unmap.find(cur);
if(index->second == i)
continue;
else
{
result.push_back(i);
result.push_back(index->second);
break;
}
}
}
return result;
}
};
这种方法更简单!运用unordered_map的性质,用时更短
class Solution {
public:
string longestPalindrome(string s) {
vector<vector<bool>> dp(s.size(),vector<bool>(s.size(),false));
int length = 0;
int maxlenth = 0;
int left = 0;
int right = 0;
for(int i = s.size()-1; i >= 0; i-- )
{
for(int j = i; j < s.size(); j++)
{
if(s[i] == s[j])
{
if(j - i <= 1)
dp[i][j] = true;
else if(dp[i+1][j-1])
dp[i][j] = true;
}
if(dp[i][j] && j-i+1 > maxlenth)
{
maxlenth = j - i + 1;
left = i;
right = j;
}
}
}
return s.substr(left,maxlenth);
}
};
回溯算法专题:
77. 组合
class Solution {
public:
vector<vector<int>> result;
void combineselect(vector<int>path , int n , int k, int index)
{
if(path.size() == k)
{
result.push_back(path);
return;
}
for(int i = index+1; i <= n; i++)
{
path.push_back(i);
combineselect(path, n, k, i);
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
vector<int> path;
result.clear();
path.clear();
combineselect(path,n,k,0);
return result;
}
};
39. 组合总和
class Solution {
public:
vector<vector<int>> result;
void backtrack(vector<int> path, vector<int>&candidates, int sum ,int target,int index)
{
if(sum == target)
{
result.push_back(path);
return;
}
if(sum > target)
return;
for(int i = index; i < candidates.size(); i++)
{
path.push_back(candidates[i]);
sum += candidates[i];
backtrack(path,candidates,sum,target,i);
sum -= candidates[i];
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<int> path;
sort(candidates.begin(),candidates.end());
backtrack(path,candidates,0,target,0);
return result;
}
};
40. 组合总和 II
class Solution {
public:
vector<vector<int>> result;
void trackback(vector<int> path, vector<int>& candidates, int target, int sum , int index)
{
if(sum == target)
{
result.push_back(path);
return;
}
if(sum > target)
return;
for(int i = index; i < candidates.size(); i++)
{
if(i > index && candidates[i] == candidates[i-1])
continue;
sum += candidates[i];
path.push_back(candidates[i]);
trackback(path,candidates,target,sum,i+1);
path.pop_back();
sum -= candidates[i];
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<int> path;
sort(candidates.begin(),candidates.end());
trackback(path,candidates,target,0,0);
return result;
}
};
代码:if(i > index && candidates[i] == candidates[i-1])
continue;
每一层的时候,都不要拿和前面一样的
216. 组合总和 III
class Solution {
public:
vector<vector<int>> result;
void backtrack(vector<int> path,int k, int n,int index,int sum)
{
if(sum == n && path.size() == k)
{
result.push_back(path);
return;
}
if(sum > n)
return;
for(int i = index ; i < 10; i++)
{
sum += i;
path.push_back(i);
backtrack(path,k,n,i+1,sum);
sum -= i;
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
vector<int> path;
backtrack(path,k,n,1,0);
return result;
}
};
17. 电话号码的字母组合
class Solution {
public:
vector<string> result;
string letter(int cur)
{
if(cur == 2)
return "abc";
if(cur == 3)
return "def";
if(cur == 4)
return "ghi";
if(cur == 5)
return "jkl";
if(cur == 6)
return "mno";
if(cur == 7)
return "pqrs";
if(cur == 8)
return "tuv";
if(cur == 9)
return "wxyz";
return "";
}
void backtrack(string digits,string path,int index)
{
if(path.size() == digits.size())
{
result.push_back(path);
return;
}
int cur = digits[index] - '0';
string letter1 = letter(cur);
for(int i = 0 ; i < letter1.size(); i++)
{
path.push_back(letter1[i]);
backtrack(digits,path,index+1);
path.pop_back();
}
}
vector<string> letterCombinations(string digits) {
if(digits.size() == 0)
return result;
string path = "";
backtrack(digits,path,0);
return result;
}
};
贪心算法:
455. 分发饼干
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
int result = 0;
int i = 0;
int j = 0;
sort(g.begin(),g.end());
sort(s.begin(),s.end());
while(i < g.size() && j < s.size())
{
if(g[i] > s[j])
{
j++;
}else
{
result++;
i++;
j++;
}
}
return result;
}
};
376. 摆动序列
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
bool pre_smaller = false;
bool pre_bigger = false;
int result = nums.size();
for(int i = 1; i < nums.size(); i++)
{
if(nums[i] > nums[i-1])
{
if(pre_bigger)
{
result--;
}else
{
pre_bigger = true;
pre_smaller = false;
}
}else if(nums[i] < nums[i-1])
{
if(pre_smaller)
{
result--;
}else{
pre_smaller = true;
pre_bigger = false;
}
}else{
result--;
}
}
return result;
}
};
这道题其实要透过现象看本质,就是找峰值啊!遇到这种题不要慌,慢慢分析
解析:代码随想录
53. 最大子数组和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int sum = 0;
sum = nums[0];
int result = sum;
for(int i = 1; i < nums.size(); i++)
{
if(sum < 0)
sum = nums[i];
else
sum += nums[i];
if(result < sum)
result = sum;
}
return result;
}
};
只要sum<0,就不加了,停止,从后面开始
局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
122. 买卖股票的最佳时机 II
class Solution {
public:
int maxProfit(vector<int>& prices) {
int sum = 0;
for(int i = 1 ; i < prices.size(); i++)
{
if(prices[i] - prices[i-1] > 0)
{
sum += prices[i] - prices[i-1];
}
}
return sum;
}
};
如果想到其实最终利润是可以分解的,那么本题就很容易了!
局部最优:收集每天的正利润,全局最优:求得最大利润。
55. 跳跃游戏
class Solution {
public:
bool canJump(vector<int>& nums) {
int cur_range = 0;
if(nums.size()== 1)
return true;
int cover =0;
for(int i =0 ; i <= cover ; i++)
{
cover = max(nums[i] + i,cover);
if(cover >= nums.size()-1)
{
return true;
}
}
return false;
}
};
局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点。
45. 跳跃游戏 II
class Solution {
public:
int jump(vector<int>& nums) {
if(nums.size() == 1)
{
return 0;
}
int curDistance = 0;
int nextDistance = 0;
int time = 0;
for(int i = 0; i <= curDistance; i++)
{
nextDistance = max(nextDistance,i+nums[i]);
if(i == curDistance)
{
time++;
curDistance = nextDistance;
if(nextDistance>= nums.size()-1)
{
break;
}
}
}
return time;
}
};
以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(),nums.end());
int sum = 0;
for(int i = 0; i < nums.size(); i++)
{
if(nums[i] < 0 && k > 0)
{
nums[i] = -nums[i];
k--;
}
sum += nums[i];
}
if(k > 0)
{
sort(nums.begin(),nums.end());
sum -= nums[0];
sum += nums[0] * pow(-1,k);
}
return sum;
}
};
局部最优:让绝对值大的负数变为正数,当前数值达到最大,整体最优:整个数组和达到最大。
动态规划专题:
动规五部曲如下:
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
53. 最大子数组和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> dp(nums.size(),0);
dp[0] = nums[0];
int result = nums[0];
for(int i = 1; i < nums.size(); i++)
{
dp[i] = max(dp[i-1]+nums[i],nums[i]);
if(dp[i] > result)
result = dp[i];
}
return result;
}
};
dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]。
dp[i]只有两个方向可以推出来:
- dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和
- nums[i],即:从头开始计算当前连续子序列和
详细思路:代码随想录
class Solution {
public:
int fib(int n) {
if(n == 0)
return 0;
if(n == 1)
return 1;
return fib(n-1)+fib(n-2);
}
};
class Solution {
public:
int climbStairs(int n) {
if(n == 1)
return 1;
vector<int> dp(n+1,0);
dp[1] = 1;
dp[2] = 2;
for(int i = 3; i <= n ; i++)
{
dp[i] = dp[i-2] + dp[i-1];
}
return dp[n];
}
};
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
vector<int> dp(cost.size()+1, 0);
if(cost.size() == 1)
return cost[0];
dp[0] = 0;
dp[1] = 0;
int n = cost.size();
for(int i = 2; i <= n ; i++)
{
dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[n];
}
};
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
dp[0][0] = 1;
for(int i = 1; i < m; i++)
{
dp[i][0] = 1;
}
for(int j = 1; j < n; j++)
{
dp[0][j] = 1;
}
for(int i = 1; i <m; i++)
{
for(int j = 1; j < n; j++)
{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
int result = dp[m-1][n-1];
return result;
}
};
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector<vector<int>> dp(m,vector<int>(n,0));
for(int i = 0; i < m; i++)
{
if(obstacleGrid[i][0] == 0)
{
dp[i][0] = 1;
}else
{
break;
}
}
for(int j = 0; j < n; j++)
{
if(obstacleGrid[0][j] == 0)
{
dp[0][j] = 1;
}else
{
break;
}
}
for(int i = 1; i <m; i++)
{
for(int j = 1; j < n; j++)
{
if(obstacleGrid[i][j] == 0)
{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}else
{
dp[i][j] = 0;
}
}
}
return dp[m-1][n-1];
}
};
单调栈
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<int> st;
vector<int> result(temperatures.size(),0);
st.push(0);
for(int i = 1; i < temperatures.size(); i++)
{
while(!st.empty() && temperatures[i] > temperatures[st.top()])
{
result[st.top()] = i - st.top();
st.pop();
}
st.push(i);
}
return result;
}
};
class Solution {
public:
int trap(vector<int>& height) {
stack<int> st;
int result = 0;
st.push(0);
for(int i = 1; i < height.size() ; i++)
{
if(height[i] < height[st.top()])
{
st.push(i);
}else if(height[i] == height[st.top()])
{
st.pop();
st.push(i);
}else
{
while(!st.empty() && height[i] > height[st.top()])
{
int mid = st.top();
st.pop();
if(!st.empty())
{
int h = min(height[i],height[st.top()]) - height[mid];
int w = i - st.top()-1;
result += h*w;
}
}
st.push(i);
}
}
return result;
}
};
讲解:代码随想录