移掉k位数字
思路:贪心+单调栈
保证元素的大小是非递减的即可。
从第二个元素开始和左边最近的一个元素相比,如果第二个元素更小,则弹栈顶元素,弹出之后需要继续比较栈顶元素和当前的遍历到的字符,并且弹出一次k需要减1;如果第二个元素更大,或者相等,则只需呀把元素入栈。如果最终k没有用完,这个时候的栈一定是非递减的,所以需要从后往前删元素,直到k用完了。如果在还没有遍历完字符串的时候k已经用完了,这个时候需要把剩下的字符全部入栈(因为剩下的元素都不能再被删掉了)。
let stack = [];
//如果字符串的位数小于等于k,都返回"0"
if(num.length <= k) return "0";
//去掉数组的前导0
function deleteItem(arr){
//如果传进来的全是0构成的字符串,则直接返回"0"
let str = arr.join("");
let len = str.length;
for(let i = 0; i < len; i++){
if(str[i] !== "0"){
return str.substring(i);
}
}
return "0";
}
//如果整个字符串是非递减的状态,就直接从尾向前删k个元素
//判断字符串是否是非递减的
function inc(num){
for(let i = 0; i < num.length - 1; i++){
if(num[i + 1] < num[i]){
return false;
}
}
return true;
}
if(inc(num)){
//删掉字符串尾部k个元素
return num.substring(0, num.length - k);
}
for(let i = 0; i < num.length; i++){
while(k > 0 && stack[stack.length - 1] > num[i]){
stack.pop();
k--;
}
if(k <= 0){
//当k的次数用完了,需要将后续的字符全部装进去
stack.push(num.slice(i));
break;
}else{
stack.push(num[i]);
}
}
//可能到最后,k还没用完,但是stack中的元素依然是非递减的,需要从后往前删元素
while(k > 0){
stack.pop();
k--;
}
//需要去除前导0,如果使用"" + Number(stack.join(""))这种方式,那么遇到大数,Number得到的结果就是Infinity。所以最好不用这种方式。
//如果stack是以0开头的,才需要去掉前导0
if(stack.join("").startsWith("0")){
return deleteItem(stack);
}else{
return stack.join("")
}
};