1 问题

琪琪喜欢旅游。有一天,她发现了一盏神灯,不幸的是,灯里的精灵不是那么善良。琪琪必须回答一个问题,然后精灵会实现她的一个梦想。问题是:给你一个整数,你需要删除 m 位数。剩下的的数字将形成一个新的整数,你要让这个整数最小。
不允许改变数字的顺序。现在你能帮助琪琪实现她的梦想吗?

2 抽象描述

给定两个正整数 x 和 m,要求从 x 中删除任意 m 位(不改变数字顺序),使得产生的正整数 r 最小。

3 解决方案


方案1

(1)思路

列出 x(位数为 n) 删除 m 位后的所有可能结果,从中找出最小值。

  1. 暂时假设 x 的前 n - m 位为最小值,记为 min
  2. 列举所有删除 x 的任意一位的结果,m 减小 1
  3. 对剩下的整数使用递归,重复 1 中操作
  4. 当 m 变为 0 时,判断当前整数是否小于 min,若是,则把 min 替换为当前整数。注意:由于整数第一位不能为 0,所以当前整数第一位为 0 时不进行替换。

(2) 实现

package lab.lab1.problem3;public class MagicLamp1 {private int min;    //最小整数public int findMin(int integer, int m) {String str = String.valueOf(integer);min = Integer.parseInt(str.substring(0, str.length() - m));delete(String.valueOf(integer), m);return min;}/*** 从字符串中删除m位字符** @param str 字符串* @param m   要删除的字符位数*/private void delete(String str, int m) {if (m == 0) {       //已经删除m位int temp = Integer.parseInt(str);if (temp < min && str.charAt(0) != '0') {   //首位不能是0min = temp;}return;}for (int i = 0; i < str.length(); i++) {    //删除字符串中任意一位String s = str.substring(0, i);s += str.substring(i + 1);delete(s, m - 1);   //用删除第i位后的字符串进行递归}}
}

方案2

(1) 思路

要找到最小整数 r,首先 r 的第一位要最小。由于不能改变数字顺序,r 的第一位在 x 里不能过于靠后。否则第一位确定后,后面的数字会不够,r 的位数会小于 n - m 位,即删除的数字超过 m 位。所以应在 x 的前 m + 1 位中找到最小值作为 r 的第一位,这样即使选择的是第 m + 1 位,舍弃掉的也是 x 的前 m 位,刚好符合题意。

举个例子,x = 4973158,m = 3,r 应该有 7 - 3 = 4 位。如果 r 的第一位取 x 所有位中的最小值 1,而 x 在 1 后面(包括 1)的数字是 158,只有 3 位,r 的位数明显不够。而在 x 的前 4 位中取最小值 3,x 在 3 后面(包括 3)的数字是 3158,恰好有 4 位,所以 r 为 3158。

(2) 实现

package lab.lab1.problem3;public class MagicLamp2 {private String result = "";private int m;private int length; //目标长度public int findMin(int integer, int m) {result = "";this.m = m;String str = String.valueOf(integer);length = str.length() - m;findMin(str, m);return Integer.parseInt(result);}private void findMin(String str, int m) {if (m == 0) {   //舍弃的位数满m位,结束递归for (int i = 0; i < str.length(); i++) {result += parseStr(str, i);}return;}if (result.length() == length) {   //结果满n-m位,结束递归return;}int minPosition;if (this.m == m) { //第一位不能为0minPosition = getMinExceptZero(str.substring(0, m + 1));} else {minPosition = getMin(str.substring(0, m + 1));}result += parseStr(str, minPosition);findMin(str.substring(minPosition + 1), m - minPosition);//已经去掉了minPosition位}/*** 获取数字最小的一位** @param str 整数字符串* @return 数字最小的一位的位置*/private int getMin(String str) {int min = parseStr(str, 0);int position = 0;for (int i = 1; i < str.length(); i++) {int temp = parseStr(str, i);if (temp < min) {min = temp;position = i;}}return position;}/*** 获取数字最小的一位(0除外)** @param str 整数字符串* @return 数字最小的一位的位置*/private int getMinExceptZero(String str) {int min = parseStr(str, 0);int position = 0;for (int i = 1; i < str.length(); i++) {int temp = parseStr(str, i);if (temp < min && temp != 0) {min = temp;position = i;}}return position;}/*** 获取整数的某位数字** @param str   字符串* @param index 第几位* @return 该位数字*/private int parseStr(String str, int index) {return str.charAt(index) - '0';}

方案比较

由于运行时间取决于 n 和 m 两个未知数,方案 2 中还与最小位的位置有关,时间复杂度较难计算,于是我们用直观的方式比较两种方案的运行时间。

测试类

package lab.lab1.problem3;public class Test {public static void main(String args[]) {MagicLamp1 magicLamp1 = new MagicLamp1();MagicLamp2 magicLamp2 = new MagicLamp2();System.out.println("m=3");long start1 = System.nanoTime();String result1 = magicLamp1.findMin("24164397292646574", 3);long end1 = System.nanoTime();System.out.println("方案1:" + result1 + "," + (end1 - start1) + "ns");long start2 = System.nanoTime();String result2 = magicLamp2.findMin("24164397292646574", 3);long end2 = System.nanoTime();System.out.println("方案2:" + result2 + "," + (end2 - start2) + "ns");System.out.println("m=8");start1 = System.nanoTime();result1 = magicLamp1.findMin("24164397292646574", 8);end1 = System.nanoTime();System.out.println("方案1:" + result1 + "," + (end1 - start1) + "ns");start2 = System.nanoTime();result2 = magicLamp2.findMin("24164397292646574", 8);end2 = System.nanoTime();System.out.println("方案2:" + result2 + "," + (end2 - start2) + "ns");System.out.println("m=2");start1 = System.nanoTime();result1 = magicLamp1.findMin("24164397292646574", 2);end1 = System.nanoTime();System.out.println("方案1:" + result1 + "," + (end1 - start1) + "ns");start2 = System.nanoTime();result2 = magicLamp2.findMin("24164397292646574", 2);end2 = System.nanoTime();System.out.println("方案2:" + result2 + "," + (end2 - start2) + "ns");}
}

输出

m=3
方案1:14397292646574,22220000ns
方案2:14397292646574,48000ns
m=8
方案1:122646574,75061188000ns
方案2:122646574,10000ns
m=2
方案1:164397292646574,494000ns
方案2:164397292646574,34000ns

可以发现,方案 2 明显比方案 1 运行速度快很多。m = 8 时,方案 1 需要一分多钟,而方案 2 只需要 10 ms。
上面控制了变量 n,同样的方式控制变量 m ,可以得到结论: n 和 m 越大,方案 2 的优势越明显。

虽然方案 2 的代码比方案 1 复杂许多,但其效率比方案 1 高非常多,值得使用。

算法初步(一)寻找最小正整数相关推荐

  1. c语言从4个整数中找最小的数,编程之法:面试和算法心得(寻找最小的k个数)...

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 输入n个整数,输出其中最小的k个. 分析与解法 解法一 要求一个序列中最小的k个数,按照惯有的思维方式,则是先对这个 ...

  2. 【408计算机考研】|【2018统考真题-41】| 给定一个含 n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数

    目录 一.题目 二.解答 三.测试数据 一.题目   给定一个含 n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算 法,找出数组中未出现的最小正整数.例如,数组{-5, 3, 2, 3}中未 ...

  3. 给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。

    笔者初涉<算法设计与分析>这门专业课,在做一些算法设计题的过程中遇到一些小感悟,特此记录和大家分享. 下面直接给出算法题目: 给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高 ...

  4. 常考数据结构与算法:数组中未出现的最小正整数

    参考博客 https://www.cnblogs.com/apeway/p/10764597.html 题目描述 给定一个无序数组arr,找到数组中未出现的最小正整数 例如arr = [-1, 2, ...

  5. 算法初步--二分法(以PAT考试A1010为例题)

    算法初步--二分法 二分法的经典问题 经典问题的微扩展 经典问题的总结 PAT考试真题A1010.Radix 后记 二分法的经典问题 从一个经典问题开始:给定一个严格递增序列,要求找到当中的某个元素所 ...

  6. 微软编程题:寻找最小的k个值

    转载自:http://blog.csdn.net/v_JULY_v/article/details/6370650 寻找最小的k个数 题目描述:5.查找最小的k个元素 题目:输入n个整数,输出其中最小 ...

  7. 【PAT】第四章 算法初步

    第四章 算法初步 目录 第四章 算法初步 4.1 排序 4.1.1 选择排序 4.1.2 插入排序 4.1.3 排序题与sort函数的应用 strcmp 计算排名 4.2 散列 4.2.1 散列 1. ...

  8. 程序员编程艺术:第三章、寻找最小的k个数

    程序员编程艺术:第三章.寻找最小的k个数 作者:July. 时间:二零一一年四月二十八日. 致谢:litaoye, strugglever,yansha,luuillu,Sorehead,及狂想曲创作 ...

  9. c语言最小费用流_策略算法工程师之路-图优化算法(一)(二分图amp;最小费用最大流)...

    目录 1.图的基本定义 2.双边匹配问题 2.1 二分图基本概念 2.2 二分图最大匹配求解 2.3 二分图最优匹配求解 2.4 二分图最优匹配建模实例 2.4.1 二分图最优匹配在师生匹配中的应用 ...

  10. 海量数据中,寻找最小的k个数。

    维护k个元素的最大堆,即用容量为k的最大堆存储最小的k个数,k1设为大顶堆中最大元素.遍历一次数列,n,每次遍历一个元素x,与堆顶元素比 较,x<kmax,更新堆,否则不更新堆. 1 // 海量 ...

最新文章

  1. Go 为什么这么“快”
  2. 优先深度搜索判断曲线相交_程序员必知的十大基础实用算法之-DFS(深度优先搜索)...
  3. c# point偏移_GMap.NET开发技巧(四)-GPS百度地图坐标偏移及地图加偏和逆向纠偏解决方法和代码...
  4. mac os 安装 pkg-config
  5. Android应用程序组件Content Provider简要介绍和学习计划
  6. 大数据薪资报告出炉:你的工资拖后腿了吗?
  7. MinGW - Minimalist GNU for Windows
  8. Flutter打包安卓提示请使用 -Xlint:deprecation 重新编译、请使用 -Xlint:unchecked 重新编译
  9. 用python写石头剪刀布_Python实现简单石头剪刀布游戏
  10. 格式化文件系统命令所在目录——command not found
  11. unity read files 从ini文件
  12. Unity之物理引擎
  13. 安卓ASO怎么做?有哪些工具平台?安卓aso工具有哪些
  14. ue4-材质编辑器material
  15. 【行业专题报告】酒类(白酒、啤酒)-专题资料
  16. 【微信小程序-初级实战】弹出海报/广告效果实现
  17. ASCII码值与字符的转换
  18. 什么是大数据和大数据平台?
  19. 如何在 SAP UI5 应用里显示 PDF 文件试读版
  20. quartus II 过期怎么办?

热门文章

  1. 股市实时行情分发工具-拿来就用
  2. 读研攻略(6)—会议纪要
  3. 24.FFmpeg学习笔记 - 用libavfilter转换原始音频格式1
  4. 基于java浏览器的设计与实现_基于java的浏览器的设计与实现论文.docx
  5. Unity导出exe时遇到的两个问题
  6. 金融业--贝塔系数、夏普比率、简森指数、特雷诺指数的含义和应用
  7. Window环境PHP7使用Protobuf开发详解
  8. 10个比较有用的jQuery插件
  9. win7定时关机命令_只需9步教你轻松设置win7系统定时关机,无需任何工具
  10. awgn信道matlab建模,正交幅度调制信号在AWGN信道中传输的MATLAB仿真