题意:给一个加密的字符串,返回原字符串
递归,模拟题
class Solution {
public:
string decodeString(string s) {
int i=0,num=0,cnt=0;string ans="",sub="";
while(i='0'){
num=num*10+s[i]-'0';i++;
}
else if(s[i]=='['){
cnt++;
while(cnt){
i++;
if(s[i]==']'){cnt--;if(!cnt)break;}
else if(s[i]=='[')cnt++;
sub+=s[i];
}
i++;
sub=decodeString(sub);
for(int i=0;i
416. Partition Equal Subset Sum
题意:分成两个子集使得两部分相等
我的思路
问是否能找到一个方法选择数组中的数字使得和为sum/2
动态规划,但首先要sort一边,同时要注意是01背包还是完全背包
要怎么才能不同时加同样的数呢?
改写dfs+记忆化了,但TLE了
代码
class Solution {
public:
bool dfs(vector& nums,int id,int res,vector& dp){
if(res<0)return 0;
if(dp[res])return 1;
if(id==nums.size())return 0;
if(nums[id]==res){
dp[res]=1;return 1;
}
bool flag=( dfs(nums,id+1,res-nums[id],dp) | dfs(nums,id+1,res,dp) );
if(flag)dp[res]=1;
return flag;
}
bool canPartition(vector& nums) {
ios::sync_with_stdio(0);cin.tie(0);
int n=nums.size();int sum=0;
for(int i=0;idp(sum,0);
return dfs(nums,0,sum,dp);
}
};
应该是01背包和分组背包类似的,但是忘记了
标答 递归+记忆化
标答的记忆化是如何过的呢?
它的记忆化不止记录了返回true的答案,也记录了返回false的答案;
返回false的答案是如何记录的呢?
首先是二维dp[id][res]来记忆结果,同时初始化为-1,这样false就记为0,True就记为1
1. 判断是否为双数可以用&1
2. 返回的时候用or,这样可以快80ms
代码 Runtime 99 ms Beats 91.9% Memory27.4 MB Beats 54.2%
class Solution {
public:
int dp[201][20001];
bool dfs(vector& nums,int id,int res){
if(res<0)return 0;
if(res==0)return 1;
if(dp[id][res]!=-1)return dp[id][res];
if(id==nums.size())return 0;
return dp[id][res]=(dfs(nums,id+1,res-nums[id]) or dfs(nums,id+1,res) );
}
bool canPartition(vector& nums) {
ios::sync_with_stdio(0);cin.tie(0);
int n=nums.size();int sum=0;
for(int i=0;i>1;
memset(dp,-1,sizeof(dp));
return dfs(nums,0,sum);
}
};
标答 动态规划
把数字放在最外层,把sum放在第二层循环里
注意第二层循环的sum是从大到小的!!!这样可以避免重拿
代码 Runtime30 ms Beats 98.21% Memory9.8 MB Beats 90.95%
class Solution {
public:
bool canPartition(vector& nums) {
ios::sync_with_stdio(0);cin.tie(0);
int n=nums.size();int sum=0;
for(int i=0;i>1;
vector dp(sum+1,0);dp[0]=1;
for(int q:nums){
for(int i=sum;i>=0;i--){
if(q<=i&&dp[i-q]) dp[i]=1;
}
}
return dp[sum];
}
};
438. Find All Anagrams in a String
题意:给字符串p,主串s,返回index,使得以s[i]开头的子串包括字符串p的所有形式
我的思路
写了暴力 TLE了
class Solution {
public:
vector findAnagrams(string s, string p) {
if(s.size() ans;int pn=p.size();
bool flag=0;
sort(p.begin(),p.end());
puts(p);
for(int i=0;i
标答 滑动窗口
和76. Minimum Window Substring思路相同Leetcode Top 100 Liked Questions(序号75~104)
同时用map(或者vector也可以)加以辅助
代码 Runtime 9 ms Beats 88.5% Memory 8.6 MB Beats 66.45%
class Solution {
public:
vector findAnagrams(string s, string p) {
vectorgoal(26),curr(26);
int pn=p.size();vector ans;
for(int i=0;i=0)curr[s[i-pn]-'a']--;
if(goal==curr)ans.push_back(i-pn+1);
}
return ans;
}
};
没细看 更优化的版本
phash是p的所有字母,counter是p字符串长度;循环字符串末尾end,将end的字符减去,如果end字符再hash中大于等于0,counter--,代表需要的字符数减少了,end++;如果counter==0表示可以加入ans了;
class Solution {
public:
vector findAnagrams(string s, string p) {
int pHash[26] = { 0 }, counter = p.length();
for (char c : p) {
++pHash[c - 'a'];
}
int start = 0, end = 0, temp = 0;
vector res;
while (end < s.length()) {
temp = s[end] - 'a';
--pHash[temp];
if (pHash[temp] >= 0) --counter;
++end;
while (counter == 0) {
temp = s[start] - 'a';
++pHash[temp];
if (pHash[temp] > 0) ++counter;
if (end - start == p.length()) {
res.push_back(start);
}
++start;
}
}
return res;
}
};
543. Diameter of Binary Tree
题意:返回树的直径
我的思路
每个结点的左边和右边都计算一次,返回长的那一条边
代码 Runtime 3 ms Beats 96.28% Memory 20.3 MB Beats 44.94%
class Solution {
public:
int dfs(TreeNode* root,int & ans){
if(root==NULL)return 0;
int l=dfs(root->left,ans);
int r=dfs(root->right,ans);
ans=max(ans,l+r);
return max(l,r)+1;
}
int diameterOfBinaryTree(TreeNode* root) {
int ans=0;
dfs(root,ans);
return ans;
}
};
560. Subarray Sum Equals K
题意:返回子序列总和等于K的个数
我的思路
动态规划?dfs大概超时,用前缀和
写了一个暴力 超时了
标答
前缀和是对的,但是可以用map辅助看前缀和-k在map中有没有,蓝桥杯的整数拼接(?)也是相同原理
注意:
1. 因为是前缀和,所以不能开两个循环,要在一个循环内搞定;
2. map是因为要记录这个前缀和出现次数;
3. 可以初始化map[0]=1,无论k是否为0,以下假设k=0
(1)当不初始化map[0]=1时,假设0在第一个,因为有直接看是否相等的特判,OK;假设0在第i个(i!=0)时,num[i-1]=num[i],所以mp[num[i-1]]存在,OK
(2)当初始化map[0]=1时,因为有直接看是否相等的特判,OK;假设0在第i个(i!=0)时,(已知mp[num[i-1]]是正确的),所以ans+=mp[nums[i-1]]是正确的
4. mp[nums[i]]++要在循环最后,不行的会变成可行的
代码 Runtime 76 ms Beats 67.97% Memory 47 MB Beats 26.84%
class Solution {
public:
int subarraySum(vector& nums, int k) {
ios::sync_with_stdio(0);cin.tie(0);
unordered_mapmp;int ans=0;
if(nums[0]==k)ans++;mp[nums[0]]++;
for(int i=1;i
优化
1. 前缀和不需要专门放在数组里,一个int就可以解决了
2. map的find看有无key,和通关key对应的键值比,速度更快
3. 取消同步这个比较玄学,在条件1和2的情况下,取消同步会慢10ms以上
代码 Runtime 52 ms Beats 99.11% Memory 41.5 MB Beats 74.75%
class Solution {
public:
int subarraySum(vector& nums, int k) {
unordered_mapmp;int ans=0;int sum=nums[0];
if(sum==k)ans++;mp[sum]++;
for(int i=1;i
567. Permutation in String
题意:如果s1的所有排列中有一个是s2的子串,返回1
我的思路
和上面的438是一样的,但可能有更简单的,但我没想出来
代码 Runtime 7 ms Beats 68.70% Memory7.3 MB Beats 62.76%
class Solution {
public:
bool checkInclusion(string s1, string s2) {
vectorgoal(26),curr(26);
for(int i=0;s1[i];i++)goal[s1[i]-'a']++;
int len=s1.size();
for(int i=0;i=len) curr[s2[i-len]-'a']--;
if(goal==curr)return 1;
}
return 0;
}
};
标答 更快的方法
少建立的一个vector,通过++和--看能否相互抵消来判断goal是否等于curr
代码 Runtime 0 ms Beats 100% Memory 7.3 MB Beats 40.58%
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int m = s1.size();
int n = s2.size();
if (m > n) return false;
vector count(26, 0);
for (int i = 0; i < m; i++) {
count[s1[i] - 'a']++;
count[s2[i] - 'a']--;
}
if (isPermutation(count))return true;
for (int i = m; i < n; i++) {
count[s2[i] - 'a']--;
count[s2[i-m] - 'a']++;
if (isPermutation(count)) return true;
}
return false;
}
private:
bool isPermutation(vector& count) {
for (int x : count) {
if (x != 0) {
return false;
}
}
return true;
}
};
704. Binary Search
题意:升序数组找数字
我的思路
lower_bound
补充例子1: nums = [-1,0,3,5,9,12], target = 2
lower_bound返回2;upper_bound返回2
补充例子2:nums = [-1,0,3,5,9,12], target = 9
lower_bound返回4;upper_bound返回5
【以上数字都是lower_bound (or upper_bound)-nums.begin() 得到的结果】
代码
class Solution {
public:
int search(vector& nums, int target) {
ios::sync_with_stdio(0);cin.tie(0);
int i=lower_bound(nums.begin(),nums.end(),target)-nums.begin();
if(nums.size()==i||nums[i]!=target)return -1;
return i;
}
};
739. Daily Temperatures
题意:给一个温度数组,问第i天后过ans[i]天的天气会更高,返回ans;若第i天之后不会有温度更高的日子返回ans[i]=0
我的思路
单调栈从大到小存?好像可以
代码 WA
看不出什么问题 但是WA了
class Solution {
public:
vector dailyTemperatures(vector& t) {
stackst;int n=t.size();
vector ans(n,0);
for(int i=0;i=t[i])st.push(i);//有等号
else{
while(!st.empty()&&t[st.top()]
标答 单调栈
上面的写法写错了 为什么呢?
注意:上面的写法 if(st.empty()||st.top()>=t[i])应该改成 if(st.empty()||t[st.top()]>=t[i])
改完后就对了
代码 Runtime 130 ms Beats 91.20% Memory107.4 MB Beats 20.42%
class Solution {
public:
vector dailyTemperatures(vector& t) {
stackst;int n=t.size();
vector ans(n,0);
for(int i=0;i
标答 不用单调栈 类似动态规划
从右到左记录最高温度;如果现在的温度t[i]大于等于最高温度,更新最高温度;
如果现在的温度t[i]小于等于最高温度,设i之后的一天为j【因为是从右往左,所以ans[j]是有纪录的】,如果t[j]>t[i],更新ans[i],如果t[j]<=t[i],j=j+ans[j]【因为第j+ans[j]天的温度一定比第j天的高】
因为不是现在的最高温度(如果等于最高温的话就不会要找之后的天了),所以ans[i]不会等于0,也就是说总会有一个j(it[i]
代码 Runtime116 ms Beats 98.10% Memory 98.6 MB Beats 87.47%
class Solution {
public:
vector dailyTemperatures(vector& t) {
int n=t.size();int hot=t[n-1];
vector ans(n,0);
for(int i=n-2;i>=0;i--){
if(t[i]>=hot){
hot=t[i];continue;
}
int j=i+1;
while(t[j]<=t[i])
j=j+ans[j];
ans[i]=j-i;
}
return ans;
}
};
994. Rotting Oranges
题意:一个格子是腐烂的橘子,周围4个相邻的橘子下一秒也会腐烂,问多久所有橘子都腐烂?
我的思路
用BFS做,队列中的节点存放(x,y,step),记录最大的step,用cnt计算所有橘子的数量,每腐烂一个橘子cnt--,当cnt!=0时返回-1,否则返回最大的step
代码
你可能感兴趣的:(leetcode,算法,数据结构,学习,c++)