1. 程式人生 > >劍指Offer:面試題32——從1到n整數中1出現的次數(java實現)

劍指Offer:面試題32——從1到n整數中1出現的次數(java實現)

問題描述:

輸入一個整數n,求1到n這n個整數的十進位制表示中1出現的次數。例如輸入12,從1到12這些整數中包含1的數字有1,10,11,12,1一共出現了5次。

思路:(不考慮時間效率的解法,肯定不是面試官期望的)

直觀想法:累加1到n中每個整數中1出現的次數。
每個整數中1出現的次數可以由除以10和模10來計算得到。

程式碼如下:

boolean invalidInput = false;

    //不考慮時間效率的解法
    public int NumberOf1Between1AndN_Solution(int n) {




        if(n <= 0
){ invalidInput = true; return 0; } int number = 0; for(int i = 1; i <= n; i++){ number += NumberOf1(i); } return number; } public int NumberOf1(int n){ int number = 0; while(n > 0){ if
(n % 10 == 1){ number++; } n = n/10; } return number; }

思路2:從數字規律著手明顯提高時間效率的解法,能讓面試官耳目一新

首先將1-n根據最高為分成兩段,比如1-21345,分為1-1345與1346-21345
從最高位開始,每次分析最高位出現1的次數(用字串)。然後剝去最高位進行遞迴求解。

程式碼:

public class Solution {
    boolean invalidInput = false
; //時間複雜度為O(logn) public int NumberOf1Between1AndN_Solution(int n) { if(n <= 0){ invalidInput = true; return 0; } StringBuilder s = new StringBuilder(((Integer)n).toString()); return NumberOf1(s); } int NumberOf1(StringBuilder s){ if(s == null || s.length() == 0 || s.charAt(0) < '0' || s.charAt(s.length()- 1) > '9'){ return 0; } int first = s.charAt(0) - '0'; int length = s.length(); if(length == 1 && first == 0){ return 0; } if(length == 1 && first > 0){ return 1; } //假設n = 21345 //numFirstDigit是數字10000 - 19999 的第一個位中的數目 int numFirstDigit = 0; if(first > 1){ numFirstDigit = PowerBase10(length - 1); }else if(first == 1){ numFirstDigit = Integer.parseInt(s.substring(1)) + 1; } //numOtherDigits是1346 - 21345除了第一位之外的數位中的數目 int numOtherDigits = first * (length - 1) * PowerBase10(length - 2); //numRecursive是1 - 1345中的數目 int numRecursive = NumberOf1(s.deleteCharAt(0)); return numFirstDigit + numOtherDigits + numRecursive; } int PowerBase10(int n){ int result = 1; for(int i = 0; i < n; i++){ result *= 10; } return result; } }