贪心02—拼接字符串使得字典顺序最小(很棒!!!)

目录

1.问题描述:

2. 知识补充—比较两个字符串的字典序:

3.思考过程: 

4.贪心策略:

5.步骤: 

6.代码实现: 

7.注意说明:

8.证明贪心策略(可以选择不看):

9.贪心算法的在笔试时的解题套路:


 

1.问题描述:

给定一个数组,里面是若干个字符串,请拼接字符串,使得字典序最小 ,返回拼接好的长字符串。

2. 知识补充—比较两个字符串的字典序:

        a)若两个字符串的长度相同,则就把它当作26进制数比较大小,如bge         b)若两个字符串不相等,则将短的那个字符串通过补零补齐,如 b000

3.思考过程: 

1)想通过所有字符串字典顺序从小到大一次拼接到一起,发现有反例。
如:str1=b,str2=ba
排序结果为b  ba    若按照字典顺序拼接到一起得bba,显然最小的拼接串应该是bab,所以这个思路就淘汰,继续思考出下一个方法。

2)str1_str2 如:str1=b,str2=ba
str1_str2=bba, str2_str1=bab, bab

4.贪心策略:

 str1_str2

5.步骤: 

step:   1)先按照贪心策略排序
           2)再将排好序的数组里面的字符串拼接到一起即为答案 

6.代码实现: 

//定义比较器
class ProgramComparator02 {
public:
	int compare(string a,string b) {
		return (a+b).compare(b+a);//如果a+b>b+a,就返回b+a
	}
};
string lowestString(vector strs){
	if (strs.empty())
		return "";
	sort(strs.begin(), strs.end(), ProgramComparator02());
	string ans;
	for (string s : strs)
		ans += s;
	return ans;
}

7.注意说明:

1)排序比较方法必须要有传递性,不能进入一个环中
比如:甲放在乙后面,乙放在丙后面,丙放在甲后面,这个排序规则就出现了环,没法排序,所以要杜绝这样的。

8.证明贪心策略(可以选择不看):

1)第一步: 证明任意排序方法具有传递性

比如:a.b≤b.a   b.c ≤c.b  则a.c≤c.b
证:几位将字符串看成26进制数,进行比较,记k^(x位数)=m(x),这里的k=26,下面的字符串都视为26进制,点视为拼接。
a.b≤b.a 可以写成  a*m(b)+b≤b*m(a)+a                            *式
b.c ≤c.b 可以写成 b*m(c)+c≤c*m(b)+b                             **式
将*式-b再乘以c得: a*m(b)*c≤b*m(a)*c+a*c-b*c             ***式
将**式-b再乘以a得:a*b*m(c)+a*c-a*b≤a*m(b)*c            ****式
比较 ***式和 ****式可知    a*b*m(c)+a*c-a*b≤b*m(a)*c+a*c-b*c     #式
整理#式得:a*m(c)+c≤c*m(a)+a     即为a.c≤c.a    
证毕!!!

2)第二步: 证明交换任意两个子串均会将字典序增大

a.若两个子串a、b相邻
   
则根据第一步证明即可得出
b.若两个子串a、b不相邻
   比如[....axyb...]交换a和b,过程如下
    [....axyb...]—>[....xayb...]—>[....xyab...]—>[....xyba...]—>[....xbya...]—>[....bxya...]
  证毕!!!

3)第三步: 证明交换任意三、四、五....个子串均会将字典序增大 

用数学归纳法证明,这里就不陈述了
 

9.贪心算法的在笔试时的解题套路:

a.实现一个不依靠贪心策略的解法x,可以用最暴力的尝试
b.脑补出贪心策略A、贪心策略B、贪心策略C...
c.用解法X和对数器,去验证每一个贪心策略,用实验的方式得知哪个贪心策略正确
d.不要去纠结贪心策略的证明 

你可能感兴趣的:(笔记,算法,算法,贪心算法,c++)