Approach
Sorting and greedy selection
For Minimum Number of Operations to Make String Sorted, the implementation first exposes a useful order, then scans that order while making locally justified choices.
- Choose the key that reveals the greedy or grouping structure.
- Sort the relevant records by that key.
- Scan in order, maintaining the invariant that makes each local choice safe.
Code notes
- 40 lines of C++ from the credited upstream file 1830.cpp.
- The implementation visibly relies on sequence storage.
- 3 loop blocks detected.
Complexity
Sorting is typically the dominant term unless the subsequent scan uses a more expensive nested operation.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution {2 public:3 int makeStringSorted(string s) {4 const int n = s.length();5 const auto [fact, invFact] = getFactAndInvFact(n);6 int ans = 0;7 vector<int> count(26);8 9 for (int i = n - 1; i >= 0; --i) {10 const int order = s[i] - 'a';11 ++count[order];12 long perm = accumulate(count.begin(), count.begin() + order, 0) *13 fact[n - 1 - i] % kMod;14 for (int j = 0; j < 26; ++j)15 perm = perm * invFact[count[j]] % kMod;16 ans = (ans + perm) % kMod;17 }18 19 return ans;20 }21 22 private:23 static constexpr int kMod = 1'000'000'007;24 25 pair<vector<long>, vector<long>> getFactAndInvFact(int n) {26 vector<long> fact(n + 1);27 vector<long> invFact(n + 1);28 vector<long> inv(n + 1);29 fact[0] = invFact[0] = 1;30 inv[0] = inv[1] = 1;31 for (int i = 1; i <= n; ++i) {32 if (i >= 2)33 inv[i] = kMod - kMod / i * inv[kMod % i] % kMod;34 fact[i] = fact[i - 1] * i % kMod;35 invFact[i] = invFact[i - 1] * inv[i] % kMod;36 }37 return {fact, invFact};38 }39};40