一、把数组排成最小的数:

1、题目:

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

2、解题思路:

重写Comparator的compare()方法。

3、代码实现:

public class Test23 {public static void main(String[] args) {int[] array = new int[]{6,2,4,41,5};PrintMinNumber(array);}//解题思路://通过比较器重写compare方法public static String PrintMinNumber(int [] numbers) {ArrayList<Integer> list = new ArrayList<>();for(int i=0;i<numbers.length;i++){list.add(numbers[i]);}Collections.sort(list,new Comparator<Integer>(){@Overridepublic int compare(Integer o1, Integer o2) {String str1=o1+""+o2;String str2=o2+""+o1;return str1.compareTo(str2);}});StringBuilder builder = new StringBuilder();for(Integer num:list){builder.append(num);}System.out.println(builder.toString());return builder.toString();}
}

二、丑数:

1、题目:

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

2、解题思路:

参考牛客网的“事无巨细,悉究本末”:https://www.nowcoder.com/questionTerminal/6aa9e04fc3794f68acf8778237ba065b

2.1 通俗易懂的解释:

首先从丑数的定义我们知道,一个丑数的因子只有2,3,5,那么丑数p = 2 ^ x * 3 ^ y * 5 ^ z,换句话说一个丑数一定由另一个丑数乘以2或者乘以3或者乘以5得到,那么我们从1开始乘以2,3,5,就得到2,3,5三个丑数,在从这三个丑数出发乘以2,3,5就得到4,6,10,6,9,15,10,15,25九个丑数,我们发现这种方法会得到重复的丑数,而且我们题目要求第N个丑数,这样的方法得到的丑数也是无序的。那么我们可以维护三个队列:

(1)丑数数组: 1

乘以2的队列:2

乘以3的队列:3

乘以5的队列:5

选择三个队列头最小的数2加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;

(2)丑数数组:1,2

乘以2的队列:4

乘以3的队列:3,6

乘以5的队列:5,10

选择三个队列头最小的数3加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;

(3)丑数数组:1,2,3

乘以2的队列:4,6

乘以3的队列:6,9

乘以5的队列:5,10,15

选择三个队列头里最小的数4加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;

(4)丑数数组:1,2,3,4

乘以2的队列:6,8

乘以3的队列:6,9,12

乘以5的队列:5,10,15,20

选择三个队列头里最小的数5加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;

(5)丑数数组:1,2,3,4,5

乘以2的队列:6,8,10,

乘以3的队列:6,9,12,15

乘以5的队列:10,15,20,25

选择三个队列头里最小的数6加入丑数数组,但我们发现,有两个队列头都为6,所以我们弹出两个队列头,同时将12,18,30放入三个队列;

……………………

2.2 疑问:

2.2.1 为什么分三个队列?

丑数数组里的数一定是有序的,因为我们是从丑数数组里的数乘以2,3,5选出的最小数,一定比以前未乘以2,3,5大,同时对于三个队列内部,按先后顺序乘以2,3,5分别放入,所以同一个队列内部也是有序的;

2.2.2 为什么比较三个队列头部最小的数放入丑数数组?

因为三个队列是有序的,所以取出三个头中最小的,等同于找到了三个队列所有数中最小的。

2.3 实现思路:

我们没有必要维护三个队列,只需要记录三个指针显示到达哪一步;“|”表示指针,arr表示丑数数组;

(1)1

|2

|3

|5

目前指针指向0,0,0,队列头arr[0] * 2 = 2,  arr[0] * 3 = 3,  arr[0] * 5 = 5

(2)1 2

2 |4

|3 6

|5 10

目前指针指向1,0,0,队列头arr[1] * 2 = 4,  arr[0] * 3 = 3, arr[0] * 5 = 5

(3)1 2 3

2| 4 6

3 |6 9

|5 10 15

目前指针指向1,1,0,队列头arr[1] * 2 = 4,  arr[1] * 3 = 6, arr[0] * 5 = 5

………………

3、代码实现:

public class Test24 {//解题思路:创建三个队列 https://www.nowcoder.com/ta/coding-interviewspublic int GetUglyNumber_Solution(int index) {if(index<7)return index;//创建三个队列的头指针,newNum代表的是选出的最小数int t2=0,t3=0,t5=0;int newNum=1;//创建一个数组,存放丑数ArrayList<Integer> list = new ArrayList<>();list.add(newNum);for(int i=1;i<index;i++){//选出三个队列里面最小的数 newNum=Math.min(list.get(t2)*2,Math.min(list.get(t3)*3,list.get(t5)*5));//这三个if有可能进入一个或者多个,进入多个是三个队列头最小的数有多个的情况if(newNum == list.get(t2)*2) t2++; if(newNum == list.get(t3)*3) t3++; if(newNum == list.get(t5)*5) t5++; list.add(newNum);}return newNum;}
}

三、二进制中1的个数:

1、题目:

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

2、思路:

第一种:使用java内置的的toBinaryString方法来实现;

第二种:利用位运算符来实现:

(1)将n与n-1做与运算,会把最右边的1去掉。比如: 1100 & 1011 = 1000 ,即 12 & 11 = 8,再利用计算器count++计算出有多少个 1 即可。

(2)详细说明:如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来他的二进制处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
(3)举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011。我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

3、代码实现:

//利用java内置的toBinaryString方法来实现:public static int NumberOf1(int n){int count = 0;String str=Integer.toBinaryString(n);for(int i=0;i<str.length();i++){if(str.charAt(i)=='1'){count++;}}return count;}//利用位运算符来实现:public static int NumberOf2(int n){int count = 0;if(n==0)return count;if(n!=0){while(n!=0){count++;n=n&(n-1);}}return count;}

四、表示数值的字符串:

1、题目:

实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

2、代码实现:

public class Test11 {private int index = 0;//第二种解法:剑指offer解法:public boolean isNumeric(char[] str){if(str.length<1){return false;}boolean flag = scanInteger(str);if(index<str.length && str[index]=='.'){index++;flag = scanUnsignedInteger(str) || flag;}if(index < str.length && (str[index] =='E' || str[index]=='e')){index++;flag = flag && scanInteger(str);}return flag && index == str.length;}private boolean scanInteger(char[] str){if(index<str.length && (str[index]=='+' || str[index]=='-') )index++;return scanUnsignedInteger(str);}private boolean scanUnsignedInteger(char[] str) {int start = index;while(index < str.length && str[index]>='0' && str[index] <='9')index++;return start<index;//是否存在整数}//第一种解法:正则表达式public boolean isNumeric1(char[] str) {String string = String.valueOf(str);return string.matches("[\\+\\-]?\\d*(\\.\\d+)?([eE][\\+\\-]?\\d+)?");}/*以下对正则进行解释:[\\+\\-]?            -> 正或负符号出现与否\\d*                 -> 整数部分是否出现,如-.34 或 +3.34均符合(\\.\\d+)?           -> 如果出现小数点,那么小数点后面必须有数字;否则一起不出现([eE][\\+\\-]?\\d+)? -> 如果存在指数部分,那么e或E肯定出现,+或-可以不出现,紧接着必须跟着整数;或者整个部分都不出现*/
}

四、替换空格:

1、题目描述:

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

2、解题思路:

第一种:从前往后替换,后面的字符要不断往后移动,要多次移动,所以效率低下;

第二种:从后往前,先计算需要多少空间,然后从后往前移动,则每个字符只为移动一次,这样效率更高一点。

3、代码实现:

 public String replaceSpace(StringBuffer str) {int spaceNum = 0;//原字符串中空格的个数for(int i = 0;i<str.length();i++){if(str.charAt(i)==' '){spaceNum++;}}int indexOld = str.length()-1;//indexOld为为替换前的str下标int newLength = str.length() + spaceNum*2;//计算空格转换成%20之后的str长度int indexNew = newLength -1;//indexNew为为把空格替换为%20后的str下标str.setLength(newLength);;//使str的长度扩大到转换成%20之后的长度,防止下标越界for(;indexOld>=0 && indexOld<indexNew;--indexOld){if(str.charAt(indexOld)==' '){str.setCharAt(indexNew--, '0');str.setCharAt(indexNew--, '2');str.setCharAt(indexNew--, '%');}else{str.setCharAt(indexNew--, str.charAt(indexOld));}}return str.toString();}
}

《剑指offer》-- 把数组排成最小的数、丑数、二进制中1的个数、表示数值的字符串、替换空格相关推荐

  1. 剑指offer 把数组排成最小的数 atoi和itoa,pow

    pow(x,y)在#include<math.h>文件中,计算x的y次方. C++引入头文件:#include <stdlib.h> 或者 #include <cstdl ...

  2. 剑指offer 旋转数组的最小数字

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组 ...

  3. [剑指offer] 旋转数组的最小数字

    本文首发于我的个人博客:尾尾部落 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2 ...

  4. 4-剑指offer: 把数组排成最小的数

    题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 代码: cl ...

  5. java中数组的下标比较_【Java】 剑指offer(53-3) 数组中数值和下标相等的元素

    本文参考自<剑指offer>一书,代码采用Java语言. 题目 假设一个单调递增的数组里的每个元素都是整数并且是唯一的.请编程实现一个函数找出数组中任意一个数值等于其下标的元素.例如,在数 ...

  6. 【LeetCode】剑指 Offer 51. 数组中的逆序对

    [LeetCode]剑指 Offer 51. 数组中的逆序对 文章目录 [LeetCode]剑指 Offer 51. 数组中的逆序对 package offer;public class Soluti ...

  7. 【LeetCode】剑指 Offer 56. 数组中数字出现的次数

    [LeetCode]剑指 Offer 56. 数组中数字出现的次数 文章目录 [LeetCode]剑指 Offer 56. 数组中数字出现的次数 package offer;import java.u ...

  8. 【LeetCode】剑指 Offer 39. 数组中出现次数超过一半的数字

    [LeetCode]剑指 Offer 39. 数组中出现次数超过一半的数字 文章目录 [LeetCode]剑指 Offer 39. 数组中出现次数超过一半的数字 一.摩尔投票法 一.摩尔投票法 核心理 ...

  9. 剑指 Offer II 061. 和最小的 k 个数对

    链接:剑指 Offer II 061. 和最小的 k 个数对 题解: class Solution { public:vector<vector<int>> kSmallest ...

最新文章

  1. 揭秘:一个月不摸鱼能写多少代码?
  2. 阿里钉钉陈航发布10亿“春雨计划”,推进企业级市场服务创新
  3. 8.使用Xshell5密钥登录liunx
  4. 5G 非独立组网链路预算公式(笔记)
  5. JaveWeb学习之Servlet(二):ServletConfig和ServletContext
  6. 免费12个月!阿里云助力中小企业0成本上云
  7. Python学习中出现的一些问题
  8. html5下input的placeholder标签兼容ie9
  9. java停止循环label_Java中的break Label 和continue Label 例子(跳出多重循环)(转)...
  10. cmd编译java代码
  11. 心理声学模型在感知音频编码中的应用
  12. NXOPEN/UG二次开发C#---获取NX的版本
  13. vue 获取汉字的全拼、简拼、首拼
  14. 我如何把薪水从 50人民币/天 提升到 100美元/小时的 (3)
  15. 图片上传 axios
  16. 小张张带你学习css美化网页,让你在学习的道路上不再孤单
  17. Maven插件仓库地址
  18. 微信小程序清除缓存clearStorageSync和removeStorageSync的区别 清除缓存问题 数据缓存详解
  19. 【关于打印errno]
  20. 腾讯、阿里之后,今日头条也入局的视频通信行业!

热门文章

  1. 四十七、Ansible自动化入门
  2. kaggle研究生招生(中)
  3. 商城客户细分数据(kaggle)
  4. sklearn数据的获取
  5. 小程序bindtap参数传递
  6. ​模型优化漫谈:BERT的初始标准差为什么是0.02?
  7. 生物岛实验室闵明玮课题组诚聘副研究员/博士后/科研助理/实习生
  8. GlobalPointer:用统一的方式处理嵌套和非嵌套NER
  9. ESRGAN:基于GAN的增强超分辨率方法(附代码解析)
  10. Let's Fork | 11 款 Github 最新「机器学习」开源项目