如:1593121212去掉3个数,剩下1121212最小。
思路如下:
删除k个,可以采用贪心算法,每次删除1个
那么每次删哪一个呢?
- 若N<2,那就不用纠结了,因为最多只有一个选择
- 若N>=2,则该整数可以写成XabY,X,Y分别是前缀和后缀,长度可以为0. a,b是相邻的两个数字,且a在b的左边。我们面临的选择就是删除a还是删除b的问题。若删除a,删除后变为XbY; 若删除b,删除后变为XaY.
(1) 若a ≠ \ne ̸=b,为了让剩下的部分最小,显然我们应该倾向于把a,b中的较大者删掉. 即若a<b, 倾向于删除b; 若a>b,倾向于删除a.
(2) 若a=b, 删除a和删除b是等价的,我们跳过a,比较b和它的后继,又变成问题(1)了。
此时我们已经能看出:
要求剩下的数字最小,从左向右扫描,找出连续的非严格递增串,删除最后一个
要求剩下的数字最大,从左向右扫描,找出连续的非严格递减串,删除最后一个。
核心代码如下:
public static int delKDigits(int number, int k, int max_or_min) {
final int GET_MIN = 0;
final int GET_MAX = 1;
int[] digits = getDigits(number);
for (int i = 0; i < k; i++) {
int newLength = digits.length - 1;
int[] digitsNew = new int[newLength];
int j = 0;
int delIndex = -1;
switch (max_or_min) {
case GET_MIN:
while (j < newLength - 1 && digits[j] <= digits[j + 1])
j++;
delIndex = j;
break;
case GET_MAX:
while (j < newLength - 1 && digits[j] >= digits[j + 1])
j++;
delIndex = j;
break;
default:
throw new IllegalArgumentException(
"max_or_in can only be either " + GET_MAX + "or " + GET_MIN + "!"
);
}
int n = 0;
for (int m =0;m < digits.length;m++) {
if (m != delIndex) {
digitsNew[n++] = digits[m];
}
}
digits = digitsNew;
}
int result = getInt(digits);
return result;
}
完整代码可在我的github上下载.