Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Miykael_xxm
leetcode
提交
6a633fa7
L
leetcode
项目概览
Miykael_xxm
/
leetcode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
leetcode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
6a633fa7
编写于
1月 19, 2021
作者:
L
lucifer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: $483
上级
8566ece3
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
144 addition
and
5 deletion
+144
-5
README.md
README.md
+1
-0
SUMMARY.md
SUMMARY.md
+1
-0
problems/483.smallest-good-base.md
problems/483.smallest-good-base.md
+135
-0
problems/488.zuma-game.md
problems/488.zuma-game.md
+5
-5
thinkings/union-find.md
thinkings/union-find.md
+2
-0
未找到文件。
README.md
浏览文件 @
6a633fa7
...
...
@@ -407,6 +407,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
-
[
0335. 路径交叉
](
./problems/335.self-crossing.md
)
-
[
0460. LFU 缓存
](
./problems/460.lfu-cache.md
)
-
[
0472. 连接词
](
./problems/472.concatenated-words.md
)
-
[
0483. 最小好进制
](
./problems/483.smallest-good-base.md
)
🆕
-
[
0488. 祖玛游戏
](
./problems/488.zuma-game.md
)
-
[
0493. 翻转对
](
./problems/493.reverse-pairs.md
)
-
[
0715. Range 模块
](
./problems/715.range-module.md
)
🆕
...
...
SUMMARY.md
浏览文件 @
6a633fa7
...
...
@@ -244,6 +244,7 @@
*
[
0335. 路径交叉
](
problems/335.self-crossing.md
)
*
[
0460. LFU缓存
](
problems/460.lfu-cache.md
)
*
[
0472. 连接词
](
problems/472.concatenated-words.md
)
*
[
0483. 最小好进制
](
./problems/483.smallest-good-base.md
)
🆕
*
[
0488. 祖玛游戏
](
problems/488.zuma-game.md
)
*
[
0493. 翻转对
](
problems/493.reverse-pairs.md
)
*
[
0715. Range 模块
](
../problems/715.range-module.md
)
🆕
...
...
problems/483.smallest-good-base.md
0 → 100644
浏览文件 @
6a633fa7
## 题目地址(483. 最小好进制)
https://leetcode-cn.com/problems/smallest-good-base/
## 题目描述
```
对于给定的整数 n, 如果n的k(k>=2)进制数的所有数位全为1,则称 k(k>=2)是 n 的一个好进制。
以字符串的形式给出 n, 以字符串的形式返回 n 的最小好进制。
示例 1:
输入:"13"
输出:"3"
解释:13 的 3 进制是 111。
示例 2:
输入:"4681"
输出:"8"
解释:4681 的 8 进制是 11111。
示例 3:
输入:"1000000000000000000"
输出:"999999999999999999"
解释:1000000000000000000 的 999999999999999999 进制是 11。
提示:
n的取值范围是 [3, 10^18]。
输入总是有效且没有前导 0。
```
## 前置知识
-
二分法
-
进制转换
## 公司
-
暂无
## 思路
题目虽然很短,题意也不难理解。但是要想做出来还是要费一番功夫的。
题目的意思是给你一个数组 n,让你返回一个进制 k,使得 n 的 k 进制表示为 1111...111,即一个全 1 的表示,并且
**需要返回满足条件最小的 k**
。
朴素的思路是一个个尝试。不过就算想要暴力求解也要一点
**进制转换**
的知识。这个知识点是: 一个数字 n 的 k 进制表示可以按照 $a
* k^0 + b *
k^1 + c
* k^2 + ... + m *
k^{N-1}$ 的方式转化为十进制,其中 N 为 数字 n 的 k 进制位数。 比如十进制 3 的二进制是为 11,其位数就是 2。再比如十进制的 199,位数为 3。由于我们要求的是位全为 1 的数,因此系数全部为 0,也就是 a,b,c ...., m 全部为 0。
因此我们可从 k = 2 开始枚举,直到 n - 1,线性尝试是否可满足条件。
> 一进制只能有 0, 不可能有 1,故不考虑。 由于 n 进行最多 n 个数,上限是 n - 1,因此我们的枚举上限也是 n - 1。
核心伪代码:
```
go
n
=
int
(
n
)
// 上面提到的 base 进制转十进制公式
func
sum_with
(
base
,
N
)
:
return
sum
(
1
*
base
**
i
for
i
in
range
(
N
))
for
k
=
2
to
n
-
1
:
if
sum_with
(
k
,
N
)
==
n
:
return
k
```
可问题是 N 如何求出呢?
朴素的思路仍然是线性枚举。但是我们的搜索区间如何确定呢?我们知道对于一个数 n 来说,其 2 进制表示的长度一定是大于 3 进制表示的长度的。更一般而言,如果 k1 > k2,那么对于一个数字 n 的 k1 进制表示的位数一定小于 k2 进行表示的位数。 因此我们的解空间就是 [1,x] 其中 x 为 n 的二进制表示的位数。也就是说,我们可逐一枚举 N 的值 N
`。
注意到,我们需要返回的是最小的 k 进制,结合前面说的进行越小 N 越大的知识,我们应该使用从后往前遍历,这样在平均意义上,时间复杂度更低。
```go
n = int(n)
// 上面提到的 base 进制转十进制公式
func sum_with(base, N):
return sum(1 * base ** i for i in range(N))
for N=x to 1:
for k=2 to n - 1:
if sum_with(k, N) == n: return k
```
注意这里的 x 到 1 的枚举没有必要线性枚举,而是可使用二分搜索的方式进行,其依据是**如果进制 k 的 N 为表示大于 n,那么 N\`表示就不用看了,肯定都大,其中 N\`是大于 N 的整数**。
让我们来计算下上面算法的时间复杂度。外层二分枚举的时间复杂度 $O(loglogn)$,内层枚举的时间复杂度是 n,sum_with 的时间复杂度为 logn,因此总的时间复杂度为 $n\times loglogn\times logn$。
到这里为止,算法勉强可以通过了。不过仍然有优化空间。注意到 sum_with 部分其实就是一个等比数列求和,因此我们可以使用等比数列求和公式从而将 sum_with 的时间复杂度降低到 $O(1)$。
即使如果算法的时间复杂度也是 $O(n\times loglogn)$,代入到题目是的数据范围 $[3, 10^{18}]$,也是在超时边缘。使用数学法降维打击可以获得更好的效率,感兴趣的可以研究一下。
## 关键点解析
- 利用等比数列求和公式可大大降低时间复杂度
- 从进制转换入手发现单调性,从而使用二分解决
## 代码
代码支持:Python3
Python3 Code:
```python
class Solution:
def smallestGoodBase(self, n: str) -> str:
n = int(n)
# 上面提到的 base 进制转十进制公式。
# 使用等比数列求和公式可简化时间复杂度
def sum_with(base, N):
return (1 - base ** N) // (1 - base)
# return sum(1 * base ** i for i in range(N))
# bin(n) 会计算出 n 的二进制表示, 其会返回形如 '0b10111' 的字符串,因此需要减去 2。
for N in range(len(bin(n)) - 2, 0, -1):
l = 2
r = n - 1
while l <= r:
mid = (l + r) // 2
v = sum_with(mid, N)
if v < n:
l = mid + 1
elif v > n:
r = mid - 1
else:
return str(mid)
``
`
**复杂度分析**
-
时间复杂度:$O(n
\t
imes loglogn)$
-
空间复杂度:$O(1)$
problems/488.zuma-game.md
浏览文件 @
6a633fa7
...
...
@@ -104,6 +104,11 @@ while i < len(board):
2.
3 回溯的过程记录全局最小值。
## 关键点解析
-
回溯模板
-
双指针写法
## 代码
代码支持:Python3
...
...
@@ -140,11 +145,6 @@ class Solution:
-
时间复杂度:$$O(2^(min(C, 5)))$$,其中 C 为连续相同颜色球的次数,比如 WWRRRR, C 就是 2, WRBDD, C 就是 4。min(C, 5) 是因为题目限定了手上球的个数不大于 5。
-
空间复杂度:$$O(min(C, 5)
*
Board)$$,其中 C 为连续相同颜色球的次数,Board 为 Board 的长度。
## 关键点解析
-
回溯模板
-
双指针写法
大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 36K star 啦。
大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
...
...
thinkings/union-find.md
浏览文件 @
6a633fa7
...
...
@@ -247,6 +247,8 @@ return True
-
[
684. 冗余连接
](
https://leetcode-cn.com/problems/redundant-connection/solution/bing-cha-ji-mo-ban-ben-zhi-jiu-shi-jian-0wz2m/
)
-
[
Forest Detection
](
https://binarysearch.com/problems/Forest-Detection
)
-
最小生成树经典算法 Kruskal
## 总结
如果题目有连通,等价的关系,那么你就可以考虑并查集,另外使用并查集的时候要注意路径压缩,否则随着树的高度增加复杂度会逐渐增大。
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录