题目:
给你一个整数num。你可以对它进行如下步骤恰好两次︰
- 选择一个数字x (o <= x <= 9) .
- 选择另一个数字y (o <= y <= 9)。数字y可以等于x。
- 将num中所有出现x的数位都用y替换。
- ·得到的新的整数不能有前导0,得到的新整数也不能是0。
- 令两次对num的操作得到的结果分别为a和b。
请你返回a和b的最大差值。
示例 1:
输入:num = 555
输出:888
解释:第一次选择 x = 5 且 y = 9 ,并把得到的新数字保存在 a 中。
第二次选择 x =5 且 y = 1 ,并把得到的新数字保存在 b 中。 现在,我们有 a = 999 和 b = 111 ,最大差值为 888
示例 2:
输入:num = 9
输出:8
解释:第一次选择 x = 9 且 y = 9 ,并把得到的新数字保存在 a 中。 第二次选择 x = 9 且 y = 1 ,并把得到的新数字保存在 b 中。 现在,我们有 a = 9 和 b = 1 ,最大差值为 8
示例 3:
输入:num = 123456
输出:820000
示例 4:
输入:num = 10000
输出:80000
示例 5:
输入:num = 9288
输出:8700
分析:
-
先看第一个例子:num = 555
输出 888
第一次选择 x = 5 且 y = 9 ,并把得到的新数字保存在 a 中。
第二次选择 x =5 且 y = 1 ,并把得到的新数字保存在 b 中。 现在,我们有 a = 999 和 b = 111 ,最大差值为 888第一次选择:x=5 y=9 此时y覆盖x 新数字a = 999 因为要最大差值,所以当b=111时侯,a-b的差值最大 因此,第二次选择y=1,x=5,y覆盖了x,此时b=111;
-
在看第二个例子:
输入:num = 123456
输出:820000num=123456,想要得到最大差值,因为只改变一种数字,很容易想到:923456-103456=82000(得到的新的整数不能有前导0,得到的新整数也不能是0)
因此,第一次选择:x=1,y=9,此时a=923456 第二次选择:因为不能有前导0,所以,此时选择x=2,y=0,此时b=103456
因此最大差值为82000.
-
因此,由上述的示例可得: 第一次选择x从最高位开始,如果最高位不为9,就覆盖9(y=9),否则就下一位,以此类推,不为9的最高位覆盖即可。
第二次因为为最小的值,所以,依然从最高位开始看,与之相反,最小数字为0,因为题目给出条件:得到的新的整数不能有前导0,所以,为了最小,x是依然从最高位开始看,如果最高位>1,那么此时令y=1,覆盖x,如果最高位是1了,此时最高位,从下一位开始,依次往后,直到在某一位数字>1(不能为1,因为前导不能为0)了,那么x就为这一位的数字,因此使得y=0最小,覆盖x,得到的b为最小值,因此a-b的差值最大。
解题代码:
方法一:暴力解题:
public int maxDiff(int num) {
int x = 0;
int y = 0;
int q=0;
String nums = String.valueOf(num);
LinkedList<String> one = new LinkedList<>();
LinkedList<String> two = new LinkedList<>();
for (int i =0;i<nums.length();i++){
one.add(String.valueOf(nums.charAt(i)));
two.add(String.valueOf(nums.charAt(i)));
}
int [] a=new int[one.size()] ;
int [] b=new int[one.size()] ;
for (int i =0;i<nums.length();i++){
a[i]= Integer.parseInt(one.get(i)) ;
b[i]= Integer.parseInt(one.get(i)) ;
}
//数组转换完成
for (int i = 0; i < a.length; i++) {
if (a[i]==1&&i==0){
q=a[i];
x=1;
y=9;
x=y;
a[i]=x;
break;
}else if (a[i]!=9){
q=a[i];
y=9;
x=q;
x=y;
a[i]=x;
break;
}
}
for (int i = 0; i < a.length; i++){
if (a[i]==q){
y=9;
x=q;
x=y;
a[i]=x;
}
}
/最大max完成
for (int i = 0; i < b.length; i++) {
if (i==0&&b[0] > 1) {
x = b[0];
q=x;
break;
}else if (b[i] > 1&&i!=0) {
x=b[i];
q=x;
break;
}
}
if (b[0] > 1){
for (int i = 0; i < b.length; i++){
y=1;
x=y;
if (b[i]==q){
b[i]=x;
}
}
}else {
for (int i = 1; i < b.length; i++){
if (b[i]==q&&b[i]==1){
y=1;
x=y;
b[i]=x;
}
else if (b[i]==q){
y=0;
x=y;
b[i]=x;
}
}
}
int max=0;
int min = 0;
for(int i=0;i<a.length;i++)
{
max=max*10+a[i];
min = min*10+b[i];
}
int dve =max-min;
return dve;
}
方法二:贪心算法:(贪心算法详解可参考贪心算法)
public int maxDiff(int num) {
StringBuffer min_num = new StringBuffer(String.valueOf(num));
StringBuffer max_num = new StringBuffer(String.valueOf(num));
// 找到一个高位替换成 9
int max_length = max_num.length();
for (int i = 0; i < max_length; ++i) {
char digit = max_num.charAt(i);
if (digit != '9') {
replace(max_num, digit, '9');
break;
}
}
// 将最高位替换成 1
// 或者找到一个与最高位不相等的高位替换成 0
int min_length = min_num.length();
for (int i = 0; i < min_length; ++i) {
char digit = min_num.charAt(i);
if (i == 0) {
if (digit != '1') {
replace(min_num, digit, '1');
break;
}
}
else {
if (digit != '0' && digit != min_num.charAt(0)) {
replace(min_num, digit, '0');
break;
}
}
}
return Integer.parseInt(max_num.toString()) - Integer.parseInt(min_num.toString());
}
public void replace(StringBuffer s, char x, char y) {
int length = s.length();
for (int i = 0; i < length; ++i) {
if (s.charAt(i) == x) {
s.setCharAt(i, y);
}
}
}
方法三:枚举
public int maxDiff(int num) {
int min_num = num;
int max_num = num;
for (int x = 0; x < 10; ++x) {
for (int y = 0; y < 10; ++y) {
String res = change(num, x, y);
// 判断是否有前导零
if (res.charAt(0) != '0') {
int res_i = Integer.parseInt(res);
min_num = Math.min(min_num, res_i);
max_num = Math.max(max_num, res_i);
}
}
}
return max_num - min_num;
}
public String change(int num, int x, int y) {
StringBuffer num_s = new StringBuffer(String.valueOf(num));
int length = num_s.length();
for (int i = 0; i < length; i++) {
char digit = num_s.charAt(i);
if (digit - '0' == x) {
num_s.setCharAt(i, (char) ('0' + y));
}
}
return num_s.toString();
}