classSolution { public: boolvalidWordAbbreviation(string word, string abbr){ word += " ", abbr += " "; // padding方便处理 int m = word.length(), n = abbr.length(), i = 0, j = 0; for (int s = 0; i < m && j < n; i += s, ++j) { if (isdigit(abbr[j])) { if (abbr[j] == '0') returnfalse; // 以0开头的数是非法的 int x = 0; // 一次性把整个数取出来 while (isdigit(abbr[j])) { x = x * 10 + abbr[j] - '0'; ++j; } --j; // 注意下标要回退一个 s = x; } else { if (word[i] != abbr[j]) returnfalse; s = 1; } } return i == m && j == n; // 最后判断是否两个指针同时达到结尾 } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { public: boolvalidWordAbbreviation(string word, string abbr){ word += " ", abbr += " "; int m = word.length(), n = abbr.length(), s = 0, i = 0, j = 0; for (; i < m && j < n; ++j) { if (isdigit(abbr[j])) { if (s == 0 && abbr[j] == '0') returnfalse; s = s * 10 + abbr[j] - '0'; } else { i += s; s = 0; if (i < m && word[i] != abbr[j]) returnfalse; ++i; } } return i == m && j == n; } };
Posted onEdited onInLeetCodeDisqus: Symbols count in article: 1.9kReading time ≈2 mins.
max heap+greedy O(nlog26) time O(26) space 跟621. Task Scheduler很像 按照字符频数由大到小放到k个slot里,用一个最大堆来维护字符顺序(频数高的在前,相同频数的ASCII码小的在前),每次从最大堆里pop出k个不同字符缓存起来并更新每个字符的频数(减1),如果字符频数不为0则加入缓存,则最后统一从缓存里加回最大堆,如果一旦中间过程中最大堆为空了而字符还没填满,说明有的字符频数过高,无法满足相同字符间距至少为k的要求,直接返回空串
classSolution { public: stringrearrangeString(string s, int k){ if (k == 0) return s; int f[26] = {0}; for (char c : s) { ++f[c - 'a']; } auto cmp = [&f](int a, int b) { return f[a] == f[b] ? a > b : f[a] < f[b]; }; // 频数高的优先,相同频数的ASCII码小的优先 priority_queue<int, vector<int>, decltype(cmp)> q(cmp); for (int i = 0; i < 26; ++i) { if (f[i] > 0) { q.push(i); } } int n = s.length(); string res; while (!q.empty()) { vector<int> v; // 每次缓存k个字符 int sz = min(k, n); // 这里由于要对n进行更新所以要提前判断还需要append几个字符 for (int i = 0; i < sz; ++i) { if (q.empty()) return""; // q为空,说明有字符过多,不满足相同字符间隔至少为k的要求 int x = q.top(); q.pop(); res += 'a' + x; if (--f[x] > 0) { // 如果放完当前字符还有剩余,则稍后放回堆 v.push_back(x); } --n; // 每append一个字符,更新需求n } for (int x : v) { // 最后统一从缓存加回最大堆 q.push(x); } } return res; } };
Posted onEdited onInLeetCodeDisqus: Symbols count in article: 1.8kReading time ≈2 mins.
可以利用358. Rearrange String k Distance Apart O(n) time O(n) space 把原字符串按字母频重组成一个字符串,再用两个指针,一个从头,一个从中间(+1),往结果字符串里插,一定可以保证没有重复字母出现 aaaaabbcc ==> ababacaca 这里需要证明:
classSolution { public: intsingleNonDuplicate(vector<int>& nums){ int n = nums.size(); int l = 0, r = n - 1; while (l < r) { int m = l + (r - l) / 2; if (nums[m] == nums[m + 1]) { if (m & 1) { r = m - 1; } else { l = m + 2; } } else { if (m & 1) { l = m + 1; } else { r = m; } } } return nums[l]; } };
too smart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: intsingleNonDuplicate(vector<int>& nums){ int n = nums.size(); int l = 0, r = n - 1; while (l < r) { int m = l + (r - l) / 2; if (nums[m] == nums[m ^ 1]) { // 任一数m异或1得到其相邻的数,偶数则是相邻较大的奇数,奇数则是相邻较小的偶数 l = m + 1; // 如果相邻两数相等,则所求的数肯定在右侧,因为两个数左边是偶数个数右边是奇数个数 } else { // 如果相邻两数不等,则所求的数要不是nums[m]要不在左侧 r = m; } } return nums[l]; } };
classSolution { public: vector<vector<int>> spiralMatrixIII(int R, int C, int r0, int c0) { vector<vector<int>> res = {{r0, c0}}; int dr[] = {0, 1, 0, -1}, dc[] = {1, 0, -1, 0}; int sz = 1, dir = 0, r = r0, c = c0; while (res.size() < R * C) { for (int i = 0; i < sz; ++i) { r += dr[dir]; c += dc[dir]; if (0 <= r && r < R && 0 <= c && c < C) { res.push_back({r, c}); } } dir = (dir + 1) % 4; // 方向每次转一下 sz += !(dir & 1); // 在每个方向上走的步数,每两个方向加一,即dir模2为0时加一 } return res; } };