删数字问题
1 问题描述
给定n位正整数a,去掉其中任意k<=n个数字后,剩下的数字按原次序排列组成一个新的正整数,对于给定的n位正整数a和正整数k,设计一个算法找出剩下数字组成的新数最小的删数方案。
对于给定的正整数a,编程计算删去k个数字后得到的最小数。
输入示例:
178543
4
输出示例:
13
2 算法设计思想
使用贪心算法,从左向右,相邻两个数字,若左边比右边大则删除,每次删除操作结束后都再次从头开始寻找。
当出现特殊情况,如数组删除k个数字(k未达到要求)后,剩下的所有数字呈递增状态时,贪心选择就会不成立,所以需要加一个特殊情况判断,一旦剩下数字递增,直接用循环从最大值处(最右边的数)开始删除,直到删除足够多个数字停止。
3 算法详细设计
(1)数据结构设计
使用长整型数存储待截取的数字,一维数组存储该数字的每一位数值,删除后该位数字所在的数组元素将被置为-1。
(2)算法模块设计
整个程序将各部分分工为四个函数,其中主函数负责接收输入的数据,调用toArray函数,将待排序的数转化为数组,其中由于java自带的Math.pow方法参数返回值均为double类型,可能存在误差,故重写了一个pow方法用于获得整数各位上的数字,贪心选择删除数字则在MSC函数中实现。
4 代码
public class Item_06 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long num;
num = sc.nextLong();
int k = sc.nextInt();
int[] arr = toArray(num, 6);
MCS(arr, 6, k);
}
/**
* 【算法思想】
* 使用贪心算法,从左向右,相邻两个数字,若左边比右边大则删除,每次删除操作结束后都再次从头开始寻找
* @param arr 源数字转成的数组
* @param n 源数字的位数
* @param k 要删除的位数
*/
private static void MCS(int[] arr, int n, int k) {
int right = arr[2]; //用来记录左、右边的数值(因为后面会通过标记数组值为零删除数字,无法使用数组下标记录右边数据)
int count = 0; //极端情况:当k次往复寻找结束后,删除数字数量小于k(num为123456时),此时自后向前逐一删除足量的数据
int RIndex = 0;
for(int i=1;i<=k;i++) { //删除k次,往复寻找k次
for(int j=1;j<n;j++) {
RIndex = j+1;
right = arr[j+1]; //标记右侧数据
while(arr[RIndex]==-1 || RIndex<n) {
RIndex++;
right = arr[RIndex]; //跳过left~right之间已删除的数据,寻找当前右边数值
}
if(arr[j]>right && arr[j]!=-1 && arr[j+1]!=-1) { //跳过左边已删除的数据(判断2),排除j往后全部为-1的情况(判断3)
arr[j]=-1; //删除数据
count++;
break; //一次查找结束
}
}
}
for(int m=n;count<k;m--) {
if(arr[m]!=-1) {
arr[m] = -1;
count++;
}
}
// System.out.println(Arrays.toString(arr)); //测试代码
for(int i=1;i<=n;i++) {
if(arr[i]!=-1 && arr[i]!=0) {
System.out.print(arr[i]);
}
}
}
/**
* java自带的Math.pow方法参数返回值均为double类型,可能存在误差,故重写了一个pow方法
* @param i 指数(i>0)
* @return 返回10的i次方
*/
private static int pow(int i) {
int p = 1;
for(; i>0; i--) {
p = p*10;
}
return p;
}
/**
* 功能:将一个n位数字转为长度为n+1的数组,数组第一位不存放数据
* @param num long型数字
* @param n 该数的位数
* @return 数组
*/
private static int[] toArray(long num, int n) {
int[] arr = new int[n+1]; //数组第一位不保存数据
for(int i=1;i<=n;i++) {
arr[i] = (int)(num/pow(n-i));
num = num%pow(n-i);
}
return arr;
}
}
5 运行测试
- 结果首位为0测试
- 递增数串测试