老样子 动态规划继续卡
知识点:模拟
效率:O(n2)Search效率,如果自己写匹配可以降低到O(n)
按照题意,只需要搜索一下有几个单词前缀为目标单词
1 2 3 4 5 6 7 8 9 10
|
var prefixCount = function(words, pref) { let ans = 0 words.forEach((x)=>ans+=(x.search(pref)==0)) return ans };
|
知识点:模拟
效率:O(n)
根据题意,统计两个字符串不同的字符的个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public: int minSteps(string s, string t) { vector<int> cnt('z'-'a'+2,0); vector<int> cnt1('z'-'a'+2,0); for(auto i:s) cnt[i-'a']++; for(auto i:t) cnt1[i-'a']++; int ans = 0; for(int i = 'a';i <= 'z';i++) { int idx = i-'a'; ans += abs(cnt[idx]-cnt1[idx]); } return ans; } }
|
知识点:二分
效率:O(nlogn)
这个题的坑点是不知道到底右区间是多少,因此采用级数扩大的方式查找右区间。
赛场上拍了一个小时,以为是方法做错了,结果发现是取值范围的问题。
他让找最小满足的数,一般找最小满足的都可以用二分。
让l在不满足的一侧,r在满足的一侧,然后通过不断求值的方式进行更新即可,最小满足条件的点即为二分查找的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| class Solution { public: long long minimumTime(vector<int>& time, int totalTrips) { if(totalTrips == 0) return 0; sort(time.begin(),time.end()); vector<pair<long long,long long>> stat; pair<long long,long long> last = {time[0],0}; for(auto i : time){ if(last.first==i) last.second++; else{ stat.push_back(last); last = {i,1}; } } stat.push_back(last); auto cal = [&stat](long long time)->long long{ long long ans = 0; for(auto &[v,n] : stat) { if(v > time) break; ans += n*(time/v); } return ans; }; long long l = 0,r = last.first; bool flag = false; bool flag1 = false; while(true) { while(!flag) { long long rr = cal(r); if(rr < totalTrips) { l=r,r *= 10; continue; } else flag = true; } long long m = (l+r) / 2; long long mm = cal(m); cout << l << " " << r << " " << m << " "<< mm << endl; if(mm < totalTrips){ l = m + 1; }else { r = m - 1; } if(l >= r) { if(cal(l)>= totalTrips) return l; if(cal(l+1)>= totalTrips) return l+1; } } return r; } };
|
知识点:动态规划
、枚举
效率:O(n)
这个题最重要的是枚举,即预处理状态。
我在比赛的时候是没有想到要预处理状态的,最核心的问题是没有看到轮胎可以重复选的设定。
枚举:跑[1,20]圈内最少需要的时间,把所有的轮胎拿过来计算cost,取min即可。
枚举边界的确定:因为2^20
就已经非常大了,所以可以非常确定的说,枚举肯定在20圈以内,是一个常数级。
假如能够理解枚举,那剩下的就很简单了,无非是怎么选的问题,是一个裸的动态规划。
可惜我没想到要枚举。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class Solution { public: int minimumFinishTime(vector<vector<int>>& tires, int changeTime, int numLaps) { vector<long long> dp(max(21,numLaps+1),1e10); vector<long long> minTrie(21,1e10); minTrie[0] = 0; for(auto i : tires) { long long now = 0; for(long long j = 1;j <= 19;j++) { long long x = i[0] * pow(i[1],j-1); now += x; if(now > 1e10) break; minTrie[j] = min(minTrie[j],now); } } dp[0] = 0; for(int i = 1;i <= 19;i++) { cout << minTrie[i] << " "; } cout << endl; for(int i = 1;i <= numLaps;i++) { for(int j = 1;j <= 19;j++) { if(i-j > 0) { dp[i] = min(dp[i],dp[i-j]+minTrie[j]+changeTime); } else if(i-j == 0) { dp[i] = min(dp[i],dp[i-j]+minTrie[j]); } } }
return dp[numLaps]; } };
|