670.最大交换
思路:解题的过程就是找到需要交换的两个数的过程。
先由任意一个例子开始思考,如2431.显而易见,最符合题意的交换方式是把4换到最高位,最高位的2换到4原来所在的那一位。
再发散思维思考,这种交换方式是否符合所有可能的例子。如果给定的数据是4231,显然4作为最高位是不能被换下去的,如果4被换下去只会让这个数变小不会变大。那么需要被换下去的数就是左数第二位。需要从低位换到高位的数则是除了4之外,这串数字中最大的一个数,也就是3.
以此类推,如果给定的数据是4312,前两位都不需要动,交换第三位和第三大的数。如果给定4321,数字串已经是从大到小排列,不需要交换。
分析到这里,我们可以抽象出交换数字时所依靠的“模板”:原数字串从大到小排列过后的数字串(即元素不变,排列顺序变化)。这是一个重要的概念。
我们把读取的数字转化为字符串:
string s = to_string(num);
把读取的字符串拷贝一份,对副本进行从大到小排序得到模板串。
sort(t.rbegin(),t.rend());
现在我们要想个办法,让cpu来判断要换哪一位。cpu不能像人眼一样“显而易见”得出结论,我们试着让它按位遍历。从分析方法中我们可以抽象出,让程序把给定串和模板串从高位到低位依次比较,如果相同,则说明第i位(当前位)不用换,继续看下一位;如果不相同,则说明给定串的第i位需要由高位换到低位,换上来的那个数字是模板串中的第i位。我们再去给定串中找到与模板串中第i位相同的数字,在给定串中进行交换。
最后把交换好的给定串再转化成字符串,就大功告成了。
参考了力扣@文刀漂洋的题解:
class Solution {
public:
int maximumSwap(int num) {
string s = to_string(num), t = s;
sort(t.rbegin(),t.rend());//从大到小排列。内存分配?
for (int i = 0; i < s.size(); i ++) {
if (s[i] != t[i]) //s是原字符串数组,t是排列好的模板
{
swap(s[i], *find(s.rbegin(), s.rend(), t[i]));
//在s中查找与t[i]相等的元素,并将s[i]与找到的元素交换
break;
}
}
return stoi(s); //将字符串转成int整数
}
};
//这代码用了好多stl