删数字问题

删数字问题

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 运行测试

  1. 结果首位为0测试
    首位为0测试
  2. 递增数串测试
    递增数串测试
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值