[LeetCode] 483. Smallest Good Base 最小的好基數


 

For an integer n, we call k>=2 a good base of n, if all digits of n base k are 1.

Now given a string representing n, you should return the smallest good base of n in string format.

Example 1:

Input: "13"
Output: "3"
Explanation: 13 base 3 is 111.

 

Example 2:

Input: "4681"
Output: "8"
Explanation: 4681 base 8 is 11111.

 

Example 3:

Input: "1000000000000000000"
Output: "999999999999999999"
Explanation: 1000000000000000000 base 999999999999999999 is 11.

 

Note:

  1. The range of n is [3, 10^18].
  2. The string representing n is always valid and will not have leading zeros.

 

這道題讓我們求最小的好基數,定義了一個大於等於2的基數k,如果可以把數字n轉化為各位都是1的數,那么就稱這個基數k是好基數。通過看題目中的三個例子,應該大致可以理解題意了吧。如果我們用k表示基數,m表示轉為全1數字的位數,那么數字n就可以拆分為:

n = 1 + k + k^2 + k^3 + ... + k^(m-1)

這是一個等比數列,中學數學的內容吧,利用求和公式可以表示為 n = (k^m - 1) / (k - 1)。我們的目標是求最小的k,那么仔細觀察這個式子,在n恆定的情況,k越小則m卻大,就是說上面的等式越長越好。下面我們來分析m的取值范圍,題目中給了n的范圍,是 [3, 10^18]。由於k至少為2,n至少為3,那么肯定至少有兩項,則 m>=2。再來看m的上限該如何求?其實也不難,想要m最大,k就要最小,k最小是2,那么m最大只能為 log2(n + 1),數字n用二進制表示的時候可拆分出的項最多。但這道題要求變換后的數各位都是1,那么我們看題目中最后一個例子,可以發現,當 k=n-1 時,一定能變成 11,所以實在找不到更小的情況下就返回 n-1。

下面我們來確定k的范圍,由於k至少為2,那么就可以根據下面這個不等式來求k的上限:

n = 1 + k + k^2 + k^3 + ... + k^(m-1) > k^(m-1)

解出 k < n^(1 / (m-1)),其實我們也可以可以通過 n < k^m - 1 來求出k的准確的下限,但由於是二分查找法,下限直接使用2也沒啥問題。分析到這里,那么解法應該已經躍然紙上了,我們遍歷所有可能的m值,然后利用二分查找法來確定k的值,對每一個k值,我們通過聯合m值算出總和 sum,然后跟n來對比即可,參見代碼如下:

 

class Solution {
public:
    string smallestGoodBase(string n) {
        long long num = stol(n);
        for (int i = log(num + 1) / log(2); i >= 2; --i) {
            long long left = 2, right = pow(num, 1.0 / (i - 1)) + 1;
            while (left < right) {
                long long mid = left + (right - left) / 2, sum = 0;
                for (int j = 0; j < i; ++j) {
                    sum = sum * mid + 1;
                }
                if (sum == num) return to_string(mid);
                if (sum < num) left = mid + 1;
                else right = mid;
            }
        }
        return to_string(num - 1);
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/483 

 

參考資料:

https://leetcode.com/problems/smallest-good-base/

https://leetcode.com/problems/smallest-good-base/discuss/96591/Java-O((logn)2)-binary-search-solution

https://leetcode.com/problems/smallest-good-base/discuss/96593/Concise-C%2B%2B-Binary-Search-solution

https://leetcode.com/problems/smallest-good-base/discuss/96590/3ms-AC-C%2B%2B-long-long-int-%2B-binary-search

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM