贪心
- 前言
- 一、交换字符使得字符串相同
- 二、贪心
- 1、分析问题的思路过程
- 2、go
- 总结
- 参考资料
前言
贪心算法,必须先看清楚有哪些选择,才能在这些选择的基础上进行贪心,做最优选择,除此之外,还得看局部最优会不会形成全局最优,否则无法贪心。
一、交换字符使得字符串相同
二、贪心
1、分析问题的思路过程
有两个问题很重要,
1.如何交换才能使两字符串相同,有哪些交换方式?
2.要想交换次数最少,选择何种方式能快点交换?
问题1)相同的字符肯定不用动,不同的字符对上下交换是无意义的,这能进行两个不同对的交叉交换。
问题2)
当两对字符对相同性质时,如y-x | y - x,一次交叉交换就能让2对字符相同,这是贪心点,是最优选择。
当两对字符对不同性质时,如y - x | x - y,一次交叉交换是不行的,得先做一次无意义的上下交换,转换成相同性质对y - x | y - x,再做一次交叉换,一共两次,这必定是次优选择。
2、go
func minimumSwap(s1 string, s2 string) int {
x,y := 0,0
for i := 0;i < len(s1);i++ {
if s1[i] != s2[i] {
if s1[i] == 'x' {
x++
}
if s1[i] == 'y' {
y++
}
}
}
// 要么两个都剩下x/y,要么都不剩,否则出现单对x/y,则无法交换成功。
if x & 1 != y & 1 {
return -1
}
return (x + 1) >> 1 + (y + 1) >> 1
}
// 寻找最小交换次数
// 当x/y的数量为奇数时,一定无法交换成功。
// 抽象,我们思考中有这个交换过程,但是结果只要交换次数,不需要具体交换过程。
// xxyy yyxx
// 不仅要理解如何交换,还得理解怎么交换更快是两字符串相同?
// x x y y x y x y x x
// x y y x y x x x y x
// 不位置不同的字符提取出来
// x y x y y x
// y x y x x y
// 上下不同,上下交换也还是不同,只能对角线交换,当不同的字符是一对时(y / x,y / x),对角线交换xy即可。
// 记录不同的x/y个数,return (x + 1) >> 1 + (y + 1) >> 1
// 经过上述分析,问题就转换成记录x/y的个数,然后各子折半取上整的总和,按照贪心的做法,一次交换尽量解决两对同性质的x/y对,最后剩下的就需要交换两次,所以取上整。
总结
1)思考问题,得有一个分析的过程,最好写下来,有助于后面的逐步分析。
2)对于贪心问题,首先得知道选择有哪些,否则无从贪起,就像这里,必须知道如何交换字符串才能得到相同字符串,知道其中的交换方式有两种,才能贪心的交换。
参考资料
[1] LeetCode 交换字符使得字符串相同