题意:面试题43. 1~n整数中1出现的次数
思路:找规律。每一位digit上的1出现的次数只与:它前面的数字high、它后面的数字low、当前位的因数\(10^{digit}\)相关。
分状况讨论:
1)第i位上的数字 == 0。1~n中,这一位上1出现的次数只与高位有关。(例如2304的第3位为0,1~2304中第3位为1的状况有001x ~ 221x,一共23 * 100个, 即high * \(10^{digit}\)个)
2)第i位上的数字 == 1。1~n中,这一位上1出现的次数和高低位都有关系。(例如2314中第3位为1,1~2314中第3位为1的状况有001x ~ 221x,2310 ~ 2314,一共high * \(10^{digit}\) + low + 1个)
3)第i位上的数字 > 1。1~n中,这一位上1出现的次数只与高位有关。(例如2304中的第2位为3,1~2304中第2位为1的状况有01xx~21xx,一共(high + 1) * \(10^{digit}\)个)git
class Solution { public int countDigitOne(int n) { int count = 0; int high = n / 10; int low = 0; int cur = n % 10; int digit = 1; while (high != 0 || cur != 0) { if (cur == 0) { count += high * digit; } else if (cur == 1) { count += high * digit + (low + 1); } else { count += (high + 1) * digit; } low += cur * digit; digit *= 10; cur = high % 10; high /= 10; } return count; } }
题意:面试题44. 数字序列中某一位的数字
思路:先判断给定的n是否在i位的范围以内(好比n在10之内,是在1位数的范围内;超过10又在100之内,是在2位数的范围内……以此类推),而后计算n是i位数的第几个数的第几位。面试
class Solution { List<Integer> list = Arrays.asList(0, 10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000); public int findNthDigit(int n) { int bit = 1; long len; while (n > 0) { len = list.get(bit) - list.get(bit - 1); if (len * bit >= n) { break; } n -= len * bit; bit ++; } int num = list.get(bit - 1) + n / bit; return String.valueOf(num).charAt(n % bit) - '0'; } }
题意:面试题45. 把数组排成最小的数
思路:自定义比较器。【对于两个数字,不能简单的将较小的数字放在前面,大的数字放在后面(如2和12,最小的数应该是122,而不是212)。】正确的作法是比较两个数字组合起来的字串,将组合后字串字典序小的放前面。数组
class Solution { public String minNumber(int[] nums) { Integer[] tmp = new Integer[nums.length]; for (int i = 0; i < tmp.length; i++) { tmp[i] = nums[i]; } Arrays.sort(tmp, (a, b) -> { String s1 = String.valueOf(a) + String.valueOf(b); String s2 = String.valueOf(b) + String.valueOf(a); return s1.compareTo(s2); }); StringBuilder sb = new StringBuilder(); for (int i : tmp) { sb.append(i); } return sb.toString(); } }
题意:面试题62. 圆圈中最后剩下的数字
思路:递归。若是只有一个数字,剩下的就是第一个位置的数字,返回便可(终止条件)。若是有n-1个数字,删除的数字是第k个数字,长度为n的时候要从第k个位置开始向后数m个位置。所以递推式为:f(n, m) = (f(n - 1, m) + m) % n。app
class Solution { public int lastRemaining(int n, int m) { if (n == 1) { return 0; } int left = lastRemaining(n - 1, m); return (m + left) % n; } }
题意:面试题64. 求1+2+…+n
思路:使用运算符短路特性+递归。ui
class Solution { public int sumNums(int n) { int res = n; boolean flag = (n > 0) && (res += sumNums(n - 1)) != 0; return res; } }