nc85. 拼接所有的字符串产生字典序最小的字符串
1. 思路一: (利用stl)
要想产生字典序最小的字符串, 只需尽量把字典序小的往前放. 所以我们进行一次排序, 将字典序小的排到前面.
但是需要注意的是, 对于两个字符串a和b, 如果直接比较a和b的字典序进行排序, 这样得到的答案将是错误的. 例如: abc
和abca
两个字符串拼接, 如果按字典序直接排, 那么得到的字符串将是abcabca
, 这显然是错误的. 故我们需要对两个字符串连接后的字典序进行比较. 所以实现时, 要对a+b和b+a 比较字典序. c++语言中, 可以直接使用 < > 这样的运算符比较.
实现如下:
class Solution { public: /** * * @param strs string字符串vector the strings * @return string字符串 */ static bool cmp(const string &a, const string &b) { return (a+b) < (b+a); // 如上面描述, 不能直接比a<b, 否则会wa } string minString(vector<string>& strs) { // 使用stl的排序 sort(strs.begin(), strs.end(), cmp); // 排序后的数组连接起来即可 string res; for (auto a : strs) { res += a; } return res; } };
- 时间复杂度: 若strs数组的长度为n, 因为进行了一轮排序, 所以整体的时间复杂度是 O(nlogn).
- 空间复杂度: 没有使用额外空间, 故空间复杂度是O(1).
思路二: 自己写快排
如果面试要求不允许使用stl? 那么我们需要自己写一个排序算法. 这里以快排为例, 毕竟大多数面试官都比较爱考快排. 思路同上, 只是把sort()替换为自己实现的快排.
先复习一下快速排序的思路:
以数组[6 4 7 1 2]
为例:
那么, 祭出我们的快速排序模板吧!
class Solution { public: /** * * @param strs string字符串vector the strings * @return string字符串 */ static bool cmp(const string &a, const string &b) { return (a+b) <= (b+a); // 这里需要注意, 要写成小于等于, 因为排序的时候, 如果遇到了相等的情况, 会出现tle, 原因是第18行的while一直不会出去 } // quicksort 快速排序算法, 待排序区间为[start, end] void quicksort(vector<string> &strs, int start, int end) { if (start >= end) return; // 递归终点: 区间不合法(长度<=0) int i = start, j = end; string p = strs[i]; // 中轴随便取,本题中取最左边的元素 while (i < j) { // 右边的字符串如果大于等于基准, 则j指针往左走 while (i<j && cmp(p, strs[j])) j--; // j指针推到第一个「严格小于」基准的, 将i换过去 strs[i] = strs[j]; // 逻辑同上, 直到ij相遇 // 这里如果cmp函数不写等号, 有可能ij永不相遇 while (i<j && cmp(strs[i], p)) i++; strs[j] = strs[i]; } // ij相遇时, 就是一轮快速排序完成, 终点赋值为中轴 strs[i] = p; quicksort(strs, start, i-1); quicksort(strs, i+1, end); } string minString(vector<string>& strs) { int n = strs.size(); quicksort(strs, 0, n-1); // 对数组strs排序 string res; for (auto a : strs) { res += a; } return res; } };
- 时间、空间复杂度同思路一