题目描述
给定一个由字符串组成的数组strs,必须把所有的字符串拼接起来,返回所有拼接结果中,字典序最小的结果。
字典序定义:Java中字符串的排序方式,比如 “abc” 和 “bce”相比,“abc” 第一位a的ASCII码小于 “bce” 第一位b的ASCII码,所以 “abc” < “bce”,所以“abc”的字典序更小。对于位数不等的字符串,“abc” 和 “be”,从各自的第一位开始比较,“abc”的a小于“be”的b,所以“abc” < “be”。
class Solution {
public:
std::string lowestString(std::vector<std::string> strs){
}
};
思路
暴力
strs中所有字符串全排列,返回所有可能的结果
class Solution {
static std::vector<std::string> removeIndexString(std::vector<std::string> arr, int index) {
int N = arr.size();
std::vector<std::string> ans(N - 1);
int ansIndex = 0;
for (int i = 0; i < N; i++) {
if (i != index) {
ans[ansIndex++] = arr[i];
}
}
return ans;
}
// strs中所有字符串全排列,返回所有可能的结果
static std::set<std::string> process(std::vector<std::string> strs){
std::set<std::string> ans;
if(strs.empty()){
ans.emplace("");
return ans;
}
for (int i = 0; i < strs.size(); ++i) {
std::string first = strs[i];
auto nexts = removeIndexString(strs, i);
auto next = process(nexts);
for(const auto& cur : next){
ans.emplace(first + cur);
}
}
return ans;
}
public:
std::string lowestString(std::vector<std::string> strs){
auto ans = process(strs);
return ans.empty() ? "" : *ans.begin();
}
};
贪心
(1)错误的贪心策略
可能最直观的解法就是,所有字符串按字典序先排序,将排序后的字符串依次拼接起来就是最后的结果。
反例:[“b”, “ba”],各字符串按字典序先排序的结果是[“b”, “ba”],最后拼接的字符串是"bba",但是本例的最终结果是"bab",因为"bab" < “bba”。所以这样的贪心策略是错的。
(2)正确的贪心策略
对于任意两个字符串 A和B,如果 A与B 的拼接结果小于 B与A 的拼接结果则A排在前面,否则B排在前面,按照这样的策略将整个字符串数组先排序一遍,再将排序后的数组挨个拼接起来得到的结果就是最终的结果。
这时候就存在一个问题了,对于任意的使用贪心策略求解的题,贪心策略的提出是比较容易的,但是如何证明它是正确的就比较难了。
不要忘了,我们有对数器啊,我们可以使用最暴力的解法获取正确答案,再和我们贪心策略获得的结果进行比较,不等则说明我们的贪心策略存在问题,那么,赶紧换另外的贪心策略。
总结:任何贪心策略都是先提出再证明,既然我们有对数器,我们何必再花大力气去用证明的方式来确定贪心策略的正确性呢?证明还是留给做学术研究的人来做吧。
class Solution {
public:
std::string lowestString(std::vector<std::string> strs){
if(strs.empty()){
return "";
}
std::sort(strs.begin(), strs.end(), [](std::string &l , std::string & r){
return (l + r) < (r + l);
});
std::string ans ;
for (auto & str : strs) {
ans += str;
}
return ans;
}
};
类似题目:179. 最大数
解答
class Solution {
public:
string largestNumber(vector<int>& nums) {
sort(nums.begin(), nums.end(), [](int a, int b) {return to_string(a) + to_string(b) > to_string(b) + to_string(a); });
string res = accumulate(nums.begin(), nums.end(), string(), [](string &s, int a) {return s + to_string(a); });
return res[0] == '0' ? "0": res; // 小心00
}
};