不只为了糊口,还要有抱负。你要想:在这个行业中,我要成为什幺样的人。

一、最大的时间

题目:

给定一个由 4 位数字组成的数组,返回可以设置的符合 24 小时制的最大时间。

最小的 24 小时制时间是 00:00,而最大的是 23:59。从 00:00 (午夜)开始算起,过得越久,时间越大。

以长度为 5 的字符串返回答案。如果不能确定有效时间,则返回空字符串。

示例:
输入:[1,2,3,4]
输出:"23:41"
输入:[5,5,5,5]
输出:""

这道题我有两种思路,一种是把所有组合情况列出来,在列的过程中把不符合条件的去掉,然后找最大的,另一种是找到最大的小时,然后找分钟,找不到就找次大的小时,再找分钟,都找不着就返回空字符串。

把所有情况列出来的问题叫做全排列问题,最简单的全排列实现方式便是for循环

public String largestTimeFromDigits(int[] A) {StringBuilder stringBuilder = new StringBuilder();for (int sum = 23; sum >= 0; sum--) {for (int i = 0; i < A.length; i++) {for (int j = 0; j < A.length; j++) {if (i != j && A[i] * 10 + A[j] == sum) {// 找到小时数后找分钟数for (int fen = 59; fen >= 0; fen--) {for (int m = 0; m < A.length; m++) {for (int n = 0; n < A.length; n++) {if (m != n && A[m] * 10 + A[n] == fen && m != i && m != j && n != i && n != j) {stringBuilder.append(A[i]);stringBuilder.append(A[j]);stringBuilder.append(':');stringBuilder.append(A[m]);stringBuilder.append(A[n]);return stringBuilder.toString();}}}}}}}}return stringBuilder.toString();}

那这种写法呢,首先就很low,其次还很累,况且写出来也很难看,我在之前的博客中有写过全排列问题的解法,我们只要在最后去除一下不符合的情况就能得到所有符合条件的时间了。对于怎么找到最大的时间也有两种方案,一种是使用list.sort(),另一种就是自己写for循环了。注意一下过滤时间,小时的最大是23,当第一位为1时第二位的范围是0到4,当第一位为2时,第二位的范围是0到3。下面这种

public static List<String> stringList=new ArrayList<>();private static String largestTimeFromDigits(int[] A) {disorder(A,0,A.length);stringList.sort(new SortByString());integerList.sort(new SortByInteger());if (stringList.size()==0)return "";return stringList.get(stringList.size()-1);}static class SortByString implements Comparator {public int compare(Object o1, Object o2) {return o1.toString().compareTo(o2.toString());}}public static void disorder(int array[],int m,int n){if (m==n){if (array[0]<=2&&array[1]<=4&&array[2]<=6){if (array[0]*1000+array[1]*100!=2400){stringList.add(array[0]+""+array[1]+":"+array[2]+""+array[3]);}}return;}else {for (int i=m;i<n;i++){swap(array,m,i);disorder(array,m+1,n);swap(array,m,i);}}}private static void swap(int[] array,int m,int n){int temp=array[m];array[m]=array[n];array[n]=temp;}

另一种实现方式便是组合小时和分钟,因为组合方式比较少,所以可以直接手动写

static String ans;public static String largestTimeFromDigits(int[] A) {ans = "";check(A[0], A[1], A[2], A[3]);check(A[0], A[2], A[1], A[3]);check(A[0], A[3], A[1], A[2]);check(A[1], A[2], A[0], A[3]);check(A[1], A[3], A[0], A[2]);check(A[2], A[3], A[0], A[1]);return ans;}public static void check(int h1, int h2, int m1, int m2) {String hour = best(h1, h2, 24);String minute = best(m1, m2, 60);if (hour.isEmpty() || minute.isEmpty()) return;String cand = hour + ":" + minute;if (cand.compareTo(ans) > 0) ans = cand;}public static String best(int d1, int d2, int limit) {int ans = Math.max(10*d1 + d2 < limit ? 10*d1 + d2 : -1,10*d2 + d1 < limit ? 10*d2 + d1 : -1);return ans >= 0 ? String.format("%02d", ans) : "";}

但这种方式我测试了一下运行100次的所需时间,几次平均下来大概在90毫秒左右,我还一种更快的算法。其实和第二种写法差别不大,只是把对字符串的操作变成了对数字的操作,因为几乎在所有的编程语言中对数字的操作永远比字符串快。但要注意的一点就是对于0的处理,这一步差不多增加了15%的运算时间。对于列表求最大值的求解也没啥变动,感觉换成for循环更快一些,感兴趣的试一下。下面方式运行1000次的耗时平均在68毫秒左右。

public static List<Integer> integerList=new ArrayList<>();private static String largestTimeFromDigits(int[] A) {disorder(A,0,A.length);integerList.sort(new SortByInteger());if (integerList.size()==0)return "";int number=integerList.get(integerList.size()-1);String hour="0"+number/100;String minute="0"+number%100;return  hour.substring(hour.length()-2)+":"+minute.substring(minute.length()-2);}static class SortByInteger implements Comparator {public int compare(Object o1, Object o2) {int a=(Integer) o1;int b=(Integer)o2;return a-b;}}public static void disorder(int array[],int m,int n){if (m==n){if (array[0]<=2&&array[1]<=4&&array[2]<=6){if (array[0]*1000+array[1]*100!=2400){integerList.add(array[0]*1000+array[1]*100+array[2]*10+array[3]);}}return;}else {for (int i=m;i<n;i++){swap(array,m,i);disorder(array,m+1,n);swap(array,m,i);}}}private static void swap(int[] array,int m,int n){int temp=array[m];array[m]=array[n];array[n]=temp;}

二、最长公共前缀

题目:

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""。

示例:

输入: ["flower","flow","flight"]
输出: "fl"

输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。

看到这道题我第一反应就是全排列加排序查找,但后来想了想,不对,想复杂了,他只是让求公共前缀,这里的公共是大家都有,不是其中几个共有,所以只要拿一个和其它所有字符串进行对比就好了。在对比之前还可以进行一些过滤,数组为0的返回空字符串,长度是1的返回本身,数组中有空字符串的直接返回空字符串,这样可以省去很多计算。

public static String longestCommonPrefix(String[] strs) {if (strs.length == 0) {return "";}else if (strs.length==1){return strs[0];}String ret = strs[0];if (ret.length()==0)return "";for (int i = 0; i< strs.length-1; i++) {if (strs[i+1].length()==0)return "";ret = compare(ret, strs[i+1]);if (ret.length() == 0) {return "";}}return ret;}public static String compare(String s1, String s2) {int min = Math.min(s1.length(), s2.length());for (int i = 0; i< min; i++) {if (s1.charAt(i) != s2.charAt(i)) {return s1.substring(0, i);}}return s1.length() == min ? s1 : s2;}

三、罗马数字转换

题目:

罗马字符对照表

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

规律:
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
    X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
    C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
示例:
输入: "III"
输出: 3

输入: "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.

输入: "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

题目很长,意思很简单,就是给你一个罗马数字表示的字符串让你转换成阿拉伯数字

你可能想上来就判断判断判断,其实不用,你找找规律,凡是大数放到小数前面的就加上,大数放到小数后面的就减去,你就从前往后循环字符串取字符判断大小就好了,写个switch把罗马单字符转换成数字。

public static int romanToInt(String s) {int result=0;int last=99999;int current=0;for (int i=0;i<s.length();i++){current=singleRomanToInt(s.charAt(i));if (last<current){result-=2*last;result+=current;}else {result+=current;}last=current;}return result;}public static int singleRomanToInt(char c){switch (c) {case 'I':return 1;case 'V':return 5;case 'X':return 10;case 'L':return 50;case 'C':return 100;case 'D':return 500;case 'M':return 1000;default:return 0;}}

四、符合规则的括号

题目:

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
   左括号必须用相同类型的右括号闭合。
   左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

示例:
输入: "()[]{}"
输出: true

输入: "([)]"
输出: false

这题就比上面那题简单明了,给你一堆括号,你判断一下是不是都有开有合。

给你的字符串可能是这样的“([{}])”,也可能是这样的“{()[]}”,还可能更复杂,对于这种问题最适合的数据结构就是栈了,从字符串不断取值,如果栈顶有和它匹配的就弹出,没有就压入。需要注意的是这题的算法时间是有要求的,它可能会给你一个几千长度的字符串让你判断,如果你要是用循环什么的肯定是来不及了,从字符串取字符也尽量不要用String.toCharArray(),这种方式比String.charAt()慢,因为转换成字符数组是用的System.arraycopy(),而charAt()是直接取值,可能一次比较差不了多少时间,但是一旦字符串长起来就差多了。

public static boolean isValid(String s) {if (s.length()==0)return true;if (s.length()%2!=0)return false;Stack<Character> stack=new Stack<>();for (int i=0;i<s.length();i++){char a=s.charAt(i);if (!stack.empty()){char b=stack.pop();if (a!=getTargetChar(b)){stack.push(b);stack.push(a);}}else {stack.push(a);}}if (stack.empty()){return true;}else {return false;}}public static char getTargetChar(char a){switch (a){case '(':return ')';case '[':return ']';case '{':return '}';}return 'X';}

JAVA入门算法题(六)相关推荐

  1. JAVA入门算法题(三)

    把敬业变成习惯.短期来看是为了雇主,长期来看是为了自己. 1.题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. 估计统计字符是所有人都做过的题 这里给出两种思路,第一种思路是比 ...

  2. 【精选】JAVA入门算法题(五)

    把敬业变成习惯.短期来看是为了雇主,长期来看是为了自己. 1.题目:重复的字符串 /*** 给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成.给定的字符串只含有小写英文字母,并且长度不超 ...

  3. 【精选】JAVA入门算法题(四)

    把敬业变成习惯.短期来看是为了雇主,长期来看是为了自己. 1.题目:全排列问题 这种问题在算法题中应用很多,主要思路是使用递归来求,求n个数的全排列就是把第一个数固定后求n-1个数的全排列,不断递归到 ...

  4. JAVA入门算法题(十四)

    一.最小的淘气值 题目: /*** 老师要给学生安排座位,经统计教室有N个双人桌,M名学生,每个学生有一个淘气值,* 要合理安排座位,使得班内同桌之和的淘气值最大值尽可能的小,输出最小值.*/ 这是一 ...

  5. JAVA入门算法题(十三)

    一.出现一次的数 题目: /*** 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素.* 说明:* 你的算法应该具有线性时间复杂度. 你可以不使用额 ...

  6. JAVA入门算法题(十)

    稳扎稳打,可攻可守.没抓在手里的成功都是不算的. 1.删除重复的数字 /*** 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次.* <p>* 示例 1:* 输入: 1-> ...

  7. JAVA入门算法题(九)

    交会修理你的朋友.这种朋友正是你人生的导师. 1.加一 /***给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一.* 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字.* 你 ...

  8. JAVA入门算法题(八)

    有志者自有千计万计,无志者只感千难万难. 1.报数序列 /*** 报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数.其前五项如下:* 1. 1* 2. 11* 3. 21* 4. 1 ...

  9. JAVA入门算法题(七)

    有志者自有千计万计,无志者只感千难万难. 1.链表合并 /*** 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的.* 输入:1->2->4, 1 ...

最新文章

  1. 静态联编与动态联编之virtual的作用
  2. 线程间的通信 共享数据安全问题
  3. 解决IE8下父容器背景图片不显示的问题
  4. Excel表格快速将公式运用到一整列
  5. python3精要(35)-模块(1)-import
  6. 地图容器自适应浏览器是什么意思_Web移动端实现自适应缩放界面的方法汇总
  7. JS----深拷贝和浅拷贝
  8. charles使用说明(基于mac)
  9. linux的initrd.img的解压和打包
  10. php 100万数据,关于批量插入数据之我见(100万级别的数据,mysql)
  11. Radware LP 增加线路接口操作
  12. 啊哈,算法!为什么你如此“谜”人!
  13. 实践php检测图片木马
  14. mysql中getdate怎么用_SQL中 getdate() 用法
  15. 微信公众号自定义模板内容换行
  16. 视频怎么做GIF表情包?教你一键生成gif动图
  17. ImageLoader 图片异步加载类库的使用
  18. 试述HDFS中的名称节点和数据节点的具体功能
  19. 1个10年工程师的心路路程(二)
  20. 星起航:现在做抖音小店晚不晚?

热门文章

  1. 中小企业战略规划如何做?
  2. bwt比对算法 C语言,python-bwt算法的编码和解码
  3. java走迷宫走一步输出一次_《 人工智能技术导论 》实验指导书.doc
  4. 开发经理应该具备怎样的素质
  5. Android开发 shape使用
  6. 包教包会 | 十分钟教你用电子表格搭建一个仓库管理软件!
  7. 自定义View(英雄联盟七星图)
  8. 三、使用 nc -lk 监听socketTextStream
  9. 小米拍照以及选取相册数据为空问题
  10. LC谐振电路应用方法