戳气球 困难
原理参考这篇文章:https://leetcode-cn.com/problems/burst-balloons/solution/c-dong-tai-gui-hua-qu-jian-dp-mo-ban-ti-by-wilson7/
class Solution {
public:
int maxCoins(vector<int>& nums) {
nums.insert(nums.begin(),1); nums.push_back(1);
//dp[i][j]表示第i至第j个元素这个区间能获得的最大硬币数
vector<vector<int>> dp(nums.size(), vector<int>(nums.size(), 0));
for(int r=2; r<nums.size(); r++) //r为区间长度
for(int i=0; i<nums.size()-r; i++){ //i为左区间
int j = i + r; //j为右区间
for(int k=i+1; k<j; k++)
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]+nums[i]*nums[k]*nums[j]);
}
return dp[0][nums.size()-1];
}
};
编辑距离 困难
想得出就想得出,想不出就想不出,尽力理解吧
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
int dp[m + 1][n + 1];
for (int i = 0; i <= m; i++)
dp[i][0] = i;
for (int j = 1; j <= n; j++)
dp[0][j] = j;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++) {
if (word1[i - 1] == word2[j - 1]) //不用改的情况
dp[i][j] = dp[i - 1][j - 1];
else //增、删、改三者取最小
dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
}
return dp[m][n];
}
};
最长连续序列 困难
并查集
初始化的时候先把数组里每个元素初始化为他的下一个数;
并的时候找他能到达的最远的数字就可以了。
class Solution {
public:
unordered_map<int,int> a;
int find(int x){
return a.count(x) ? a[x]=find(a[x]) : x;
}
int longestConsecutive(vector<int>& nums) {
for(auto i:nums)
a[i] = i+1;
int ans = 0;
for(auto i:nums){
int y = find(i+1);
ans = max(ans, y-i);
}
return ans;
}
};
哈希表法
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_map<int,int> a;
for(auto i:nums)
a[i] = i;
int ans = 0;
for(int i=nums.size()-1; i>=0; --i){
if(!a.count(nums[i]-1)){
int cur = nums[i];
while(a.count(cur+1)){
++cur;
}
ans=max(ans,cur-nums[i]+1);
}
}
return ans;
}
};
二叉树的序列化与反序列化 困难
class Codec {//根据题意,我们可以任意选择序列化的方式,前序最容易构建树,我们选择前序
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string res;
dfs_s(root, res);
return res;
}
// 前序遍历序列转化为字符串
void dfs_s(TreeNode* root, string& res) {
if (!root) {
res += "null ";
return;
}
res += to_string(root->val) + ' ';
dfs_s(root->left, res);
dfs_s(root->right, res);
}
// 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 (u >= data.size()) return NULL;
if (data[u] == 'n') {//处理null
u = u + 5;
return NULL;
}
int val = 0, sign = 1;
if (data[u] == '-') sign = -1, u ++ ;
while(data[u] != ' '){val = val * 10 + data[u] - '0'; u++;}
val *= sign;
u = u + 1 ;
auto root = new TreeNode(val);
root->left = dfs_d(data, u);
root->right = dfs_d(data, u);
return root;
}
};
滑动窗口最大值 困难
这道题用deque,保持队列头部始终是最大值
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
deque<int> que;
int left=0, right=0;
for (auto num:nums){
while(!que.empty() && que.back() < num){
que.pop_back();
}
que.push_back(num);
right++;
if (right-left >=k){
res.push_back(que.front());
if (nums[left] == que.front())
que.pop_front();
left++;
}
}
return res;
}
};
缺失的第一个正数 困难
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
if (nums.empty()) return 1;
vector<int> vec(nums.size(), 0);
for (auto num:nums){
if (num > 0 && num <= nums.size())
vec[num-1] = 1;
}
int res = -1;
for (int i=0; i<vec.size(); i++){
if (vec[i] == 0){
res = i+1;
break;
}
}
if (res == -1) return nums.size()+1;
return res;
}
};
剑指 Offer 51. 数组中的逆序对 困难
class Solution {
int res = 0;
void mergeSort(vector<int>& nums, vector<int>& temp, int l, int r){
if (l >= r) return;
int mid = (l + r) / 2;
mergeSort(nums, temp, l, mid);
mergeSort(nums, temp, mid+1, r);
int i=l, j=mid+1; int t=0;
while (i<=mid && j<=r){
if (nums[i] <= nums[j]){
res += (j - (mid + 1));//这里增加一行
temp[t++] = nums[i++];
}
else
temp[t++] = nums[j++];
}
while (i <= mid) {temp[t++] = nums[i++]; res += (j-(mid+1));}//这里增加一行
while (j <= r) temp[t++] = nums[j++];
t = 0;
for (int i=l; i<=r; i++)
nums[i] = temp[t++];
}
public:
int reversePairs(vector<int>& nums) {
vector<int> temp(nums.begin(), nums.end());
mergeSort(nums, temp, 0, nums.size()-1);
return res;
}
};
逆波兰表达式求值(栈实现) 中等
class Solution {
public:
int ans;
int evalRPN(vector<string>& tokens) {
stack<int> stk;
int str_mid1, str_mid2;
for (auto v_mate : tokens) {
if (v_mate == "+") {
str_mid1 = stk.top();
stk.pop();
str_mid2 = stk.top();
stk.pop();
stk.push(str_mid2 + str_mid1);
}
else if (v_mate == "-") {
str_mid1 = stk.top();
stk.pop();
str_mid2 = stk.top();
stk.pop();
stk.push(str_mid2 - str_mid1);
}
else if (v_mate == "*") {
str_mid1 = stk.top();
stk.pop();
str_mid2 = stk.top();
stk.pop();
stk.push(str_mid2 * str_mid1);
}
else if (v_mate == "/") {
str_mid1 = stk.top();
stk.pop();
str_mid2 = stk.top();
stk.pop();
stk.push(str_mid2 / str_mid1);
}
else stk.push(atoi(v_mate.c_str()));
}
ans = stk.top();
return ans;
}
};
字典序的第K小数字 困难
class Solution {
public:
int findKthNumber(int n, int k) {
int cur = 1;
--k;
while (k > 0){
//first是当前前缀, last是下一个前缀
long long first=cur, last=cur+1, step=0;
while(first <= n){
//下一个前缀的起点减去当前前缀的起点
step += min((long long)n+1,last) - first;
first *= 10;
last *= 10;
}
if(step <= k){
k -= step;
cur++;
}
else{
k--;
cur *= 10;
}
}
return cur;
}
};