題意:面試題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; } }