劍指 offer——其餘類

43. 1~n整數中1出現的次數

題意:面試題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. 數字序列中某一位的數字

題意:面試題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. 把數組排成最小的數

題意:面試題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. 圓圈中最後剩下的數字

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

題意:面試題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;
    }
}
相關文章
相關標籤/搜索