Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
coolalex776
Fucking Algorithm
提交
e36b4778
F
Fucking Algorithm
项目概览
coolalex776
/
Fucking Algorithm
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
Fucking Algorithm
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
e36b4778
编写于
11月 12, 2020
作者:
V
Volvane
提交者:
GitHub
11月 12, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into gowufang-patch-1
上级
65e137ed
372b92bf
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
365 addition
and
29 deletion
+365
-29
动态规划系列/动态规划之博弈问题.md
动态规划系列/动态规划之博弈问题.md
+73
-3
动态规划系列/动态规划设计:最长递增子序列.md
动态规划系列/动态规划设计:最长递增子序列.md
+47
-7
动态规划系列/团灭股票问题.md
动态规划系列/团灭股票问题.md
+2
-2
动态规划系列/抢房子.md
动态规划系列/抢房子.md
+63
-2
动态规划系列/最优子结构.md
动态规划系列/最优子结构.md
+1
-1
动态规划系列/最长公共子序列.md
动态规划系列/最长公共子序列.md
+26
-2
动态规划系列/高楼扔鸡蛋问题.md
动态规划系列/高楼扔鸡蛋问题.md
+1
-1
数据结构系列/二叉搜索树操作集锦.md
数据结构系列/二叉搜索树操作集锦.md
+33
-2
算法思维系列/双指针技巧.md
算法思维系列/双指针技巧.md
+22
-2
算法思维系列/滑动窗口技巧.md
算法思维系列/滑动窗口技巧.md
+2
-2
高频面试系列/LRU算法.md
高频面试系列/LRU算法.md
+32
-1
高频面试系列/合法括号判定.md
高频面试系列/合法括号判定.md
+25
-2
高频面试系列/打印素数.md
高频面试系列/打印素数.md
+38
-2
未找到文件。
动态规划系列/动态规划之博弈问题.md
浏览文件 @
e36b4778
...
...
@@ -22,7 +22,7 @@
上一篇文章
[
几道智力题
](
https://labuladong.gitbook.io/algo
)
中讨论到一个有趣的「石头游戏」,通过题目的限制条件,这个游戏是先手必胜的。但是智力题终究是智力题,真正的算法问题肯定不会是投机取巧能搞定的。所以,本文就借石头游戏来讲讲「假设两个人都足够聪明,最后谁会获胜」这一类问题该如何用动态规划算法解决。
博弈类问题的套路都差不多,下文
举例
讲解,其核心思路是在二维 dp 的基础上使用元组分别存储两个人的博弈结果。掌握了这个技巧以后,别人再问你什么俩海盗分宝石,俩人拿硬币的问题,你就告诉别人:我懒得想,直接给你写个算法算一下得了。
博弈类问题的套路都差不多,下文
参考
[
这个 YouTube 视频
](
https://www.youtube.com/watch?v=WxpIHvsu1RI
)
的思路
讲解,其核心思路是在二维 dp 的基础上使用元组分别存储两个人的博弈结果。掌握了这个技巧以后,别人再问你什么俩海盗分宝石,俩人拿硬币的问题,你就告诉别人:我懒得想,直接给你写个算法算一下得了。
我们「石头游戏」改的更具有一般性:
...
...
@@ -215,4 +215,75 @@ int stoneGame(int[] piles) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
python3版本
由
[
SCUHZS
](
https://github.com/brucecat
)
提供
这里采取的是三维的做法
```
python
class
Solution
:
def
stoneGame
(
self
,
piles
:
List
[
int
])
->
bool
:
n
=
len
(
piles
)
# 初始化一个n*n的矩阵 dp数组
dp
=
[[
None
]
*
n
for
i
in
range
(
0
,
n
)]
# 在三角区域填充
for
i
in
range
(
n
):
for
j
in
range
(
i
,
n
):
dp
[
i
][
j
]
=
[
0
,
0
]
# 填入base case
for
i
in
range
(
0
,
n
):
dp
[
i
][
i
][
0
]
=
piles
[
i
]
dp
[
i
][
i
][
1
]
=
0
# 斜着遍历数组
for
l
in
range
(
2
,
n
+
1
):
for
i
in
range
(
0
,
n
-
l
+
1
):
j
=
l
+
i
-
1
# 先手选择最左边或最右边的分数
left
=
piles
[
i
]
+
dp
[
i
+
1
][
j
][
1
]
right
=
piles
[
j
]
+
dp
[
i
][
j
-
1
][
1
]
# 套用状态转移方程
if
left
>
right
:
dp
[
i
][
j
][
0
]
=
left
dp
[
i
][
j
][
1
]
=
dp
[
i
+
1
][
j
][
0
]
else
:
dp
[
i
][
j
][
0
]
=
right
dp
[
i
][
j
][
1
]
=
dp
[
i
][
j
-
1
][
0
]
res
=
dp
[
0
][
n
-
1
]
return
res
[
0
]
-
res
[
1
]
>
0
```
压缩成一维数组,以减小空间复杂度,做法如下。
```
python
class
Solution
:
def
stoneGame
(
self
,
piles
:
List
[
int
])
->
bool
:
dp
=
piles
.
copy
()
for
i
in
range
(
len
(
piles
)
-
1
,
-
1
,
-
1
):
# 从下往上遍历
for
j
in
range
(
i
,
len
(
piles
)):
# 从前往后遍历
dp
[
j
]
=
max
(
piles
[
i
]
-
dp
[
j
],
piles
[
j
]
-
dp
[
j
-
1
])
# 计算之后覆盖一维数组的对应位置
return
dp
[
len
(
piles
)
-
1
]
>
0
```
动态规划系列/动态规划设计:最长递增子序列.md
浏览文件 @
e36b4778
...
...
@@ -10,8 +10,8 @@
![](
../pictures/souyisou.png
)
相关推荐:
*
[
动态规划设计:最大子数组
](
../动态规划系列/最大子数组.md
)
*
[
一文学会递归解题
](
../投稿/一文学会递归解题.md
)
*
[
动态规划设计:最大子数组
](
https://labuladong.gitbook.io/algo
)
*
[
一文学会递归解题
](
https://labuladong.gitbook.io/algo
)
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
...
...
@@ -19,7 +19,7 @@
**-----------**
也许有读者看了前文
[
动态规划详解
](
../动态规划系列/动态规划详解进阶.md
)
,学会了动态规划的套路:找到了问题的「状态」,明确了
`dp`
数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?
也许有读者看了前文
[
动态规划详解
](
https://labuladong.gitbook.io/algo
)
,学会了动态规划的套路:找到了问题的「状态」,明确了
`dp`
数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?
不要担心,动态规划的难点本来就在于寻找正确的状态转移方程,本文就借助经典的「最长递增子序列问题」来讲一讲设计动态规划的通用技巧:
**数学归纳思想**
。
...
...
@@ -43,7 +43,7 @@
**我们的定义是这样的:`dp[i]` 表示以 `nums[i]` 这个数结尾的最长递增子序列的长度。**
PS:为什么这样定义呢?这是解决子序列问题的一个套路,后文
[
动态规划之子序列问题解题模板
](
../动态规划系列/子序列问题模板.md
)
总结了几种常见套路。你读完本章所有的动态规划问题,就会发现
`dp`
数组的定义方法也就那几种。
PS:为什么这样定义呢?这是解决子序列问题的一个套路,后文
[
动态规划之子序列问题解题模板
](
https://labuladong.gitbook.io/algo
)
总结了几种常见套路。你读完本章所有的动态规划问题,就会发现
`dp`
数组的定义方法也就那几种。
根据这个定义,我们就可以推出 base case:
`dp[i]`
初始值为 1,因为以
`nums[i]`
结尾的最长递增子序列起码要包含它自己。
...
...
@@ -164,7 +164,7 @@ public int lengthOfLIS(int[] nums) {
我们只要把处理扑克牌的过程编程写出来即可。每次处理一张扑克牌不是要找一个合适的牌堆顶来放吗,牌堆顶的牌不是
**有序**
吗,这就能用到二分查找了:用二分查找来搜索当前牌应放置的位置。
PS:旧文
[
二分查找算法详解
](
../算法思维系列/二分查找详解.md
)
详细介绍了二分查找的细节及变体,这里就完美应用上了,如果没读过强烈建议阅读。
PS:旧文
[
二分查找算法详解
](
https://labuladong.gitbook.io/algo
)
详细介绍了二分查找的细节及变体,这里就完美应用上了,如果没读过强烈建议阅读。
```
java
public
int
lengthOfLIS
(
int
[]
nums
)
{
...
...
@@ -215,4 +215,45 @@ public int lengthOfLIS(int[] nums) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
Kian
](
https://github.com/KianKw/
)
提供 C++ 代码
```
c++
class
Solution
{
public:
int
lengthOfLIS
(
vector
<
int
>&
nums
)
{
/* len 为牌的数量 */
int
len
=
nums
.
size
();
vector
<
int
>
top
(
len
,
0
);
/* 牌堆数初始化为0 */
int
piles
=
0
;
for
(
int
i
=
0
;
i
<
len
;
i
++
)
{
/* nums[i] 为要处理的扑克牌 */
int
poker
=
nums
[
i
];
/***** 搜索左侧边界的二分查找 *****/
int
left
=
0
,
right
=
piles
;
while
(
left
<
right
)
{
int
mid
=
left
+
(
right
-
left
)
/
2
;
if
(
top
[
mid
]
>
poker
)
{
right
=
mid
;
}
else
if
(
top
[
mid
]
<
poker
)
{
left
=
mid
+
1
;
}
else
if
(
top
[
mid
]
==
poker
)
{
right
=
mid
;
}
}
/*********************************/
/* 没找到合适的牌堆,新建一堆 */
if
(
left
==
piles
)
piles
++
;
/* 把这张牌放到牌堆顶 */
top
[
left
]
=
poker
;
}
/* 牌堆数就是 LIS 长度 */
return
piles
;
}
};
```
动态规划系列/团灭股票问题.md
浏览文件 @
e36b4778
...
...
@@ -16,7 +16,7 @@
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
[
买卖股票的最佳时机
](
https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
/solution/
)
[
买卖股票的最佳时机
](
https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
)
[
买卖股票的最佳时机 II
](
https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/
)
...
...
@@ -32,7 +32,7 @@
很多读者抱怨 LeetCode 的股票系列问题奇技淫巧太多,如果面试真的遇到这类问题,基本不会想到那些巧妙的办法,怎么办?
**所以本文拒绝奇技淫巧,而是稳扎稳打,只用一种通用方法解决所用问题,以不变应万变**
。
这篇文章用状态机的技巧来解决,可以全部提交通过。不要觉得这个名词高大上,文学词汇而已,实际上就是 DP table,看一眼就明白了。
这篇文章
参考
[
英文版高赞题解
](
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/discuss/108870/Most-consistent-ways-of-dealing-with-the-series-of-stock-problems
)
的思路,
用状态机的技巧来解决,可以全部提交通过。不要觉得这个名词高大上,文学词汇而已,实际上就是 DP table,看一眼就明白了。
先随便抽出一道题,看看别人的解法:
...
...
动态规划系列/抢房子.md
浏览文件 @
e36b4778
...
...
@@ -258,4 +258,66 @@ int[] dp(TreeNode root) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
Shantom
](
https://github.com/Shantom
)
提供 198. House Robber I Python3 解法代码:
```
Python
class Solution:
def rob(self, nums: List[int]) -> int:
# 当前,上一间,上上间
cur, pre1, pre2 = 0, 0, 0
for num in nums:
# 当前 = max(上上间+(抢当前),上间(放弃当前))
cur = max(pre2 + num, pre1)
pre2 = pre1
pre1 = cur
return cur
```
[
Shantom
](
https://github.com/Shantom
)
提供 213. House Robber II Python3 解法代码:
```
Python
class Solution:
def rob(self, nums: List[int]) -> int:
# 只有一间时不成环
if len(nums) == 1:
return nums[0]
# 该函数同198题
def subRob(nums: List[int]) -> int:
# 当前,上一间,上上间
cur, pre1, pre2 = 0, 0, 0
for num in nums:
# 当前 = max(上上间+(抢当前),上间(放弃当前))
cur = max(pre2 + num, pre1)
pre2 = pre1
pre1 = cur
return cur
# 不考虑第一间或者不考虑最后一间
return max(subRob(nums[:-1]), subRob(nums[1:]))
```
[
Shantom
](
https://github.com/Shantom
)
提供 337. House Robber III Python3 解法代码:
```
Python
class Solution:
def rob(self, root: TreeNode) -> int:
# 返回值0项为不抢该节点,1项为抢该节点
def dp(root):
if not root:
return 0, 0
left = dp(root.left)
right = dp(root.right)
# 抢当前,则两个下家不抢
do = root.val + left[0] + right[0]
# 不抢当前,则下家随意
do_not = max(left) + max(right)
return do_not, do
return max(dp(root))
```
动态规划系列/最优子结构.md
浏览文件 @
e36b4778
...
...
@@ -54,7 +54,7 @@ return result;
当然,上面这个例子太简单了,不过请读者回顾一下,我们做动态规划问题,是不是一直在求各种最值,本质跟我们举的例子没啥区别,无非需要处理一下重叠子问题。
前文不
[
同定义不同解法
](
../动态规划系列/动态规划之四键键盘.md
)
和
[
高楼扔鸡蛋进阶
](
../动态规划系列/高楼扔鸡蛋问题.md
)
就展示了如何改造问题,不同的最优子结构,可能导致不同的解法和效率。
前文不
[
同定义不同解法
](
https://labuladong.gitbook.io/algo
)
和
[
高楼扔鸡蛋进阶
](
https://labuladong.gitbook.io/algo
)
就展示了如何改造问题,不同的最优子结构,可能导致不同的解法和效率。
再举个常见但也十分简单的例子,求一棵二叉树的最大值,不难吧(简单起见,假设节点中的值都是非负数):
...
...
动态规划系列/最长公共子序列.md
浏览文件 @
e36b4778
...
...
@@ -147,4 +147,29 @@ else:
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
Shawn
](
https://github.com/Shawn-Hx
)
提供 Java 代码:
```
java
public
int
longestCommonSubsequence
(
String
text1
,
String
text2
)
{
// 字符串转为char数组以加快访问速度
char
[]
str1
=
text1
.
toCharArray
();
char
[]
str2
=
text2
.
toCharArray
();
int
m
=
str1
.
length
,
n
=
str2
.
length
;
// 构建dp table,初始值默认为0
int
[][]
dp
=
new
int
[
m
+
1
][
n
+
1
];
// 状态转移
for
(
int
i
=
1
;
i
<=
m
;
i
++)
for
(
int
j
=
1
;
j
<=
n
;
j
++)
if
(
str1
[
i
-
1
]
==
str2
[
j
-
1
])
// 找到LCS中的字符
dp
[
i
][
j
]
=
dp
[
i
-
1
][
j
-
1
]
+
1
;
else
dp
[
i
][
j
]
=
Math
.
max
(
dp
[
i
-
1
][
j
],
dp
[
i
][
j
-
1
]);
return
dp
[
m
][
n
];
}
```
动态规划系列/高楼扔鸡蛋问题.md
浏览文件 @
e36b4778
...
...
@@ -243,7 +243,7 @@ def superEggDrop(self, K: int, N: int) -> int:
return
dp
(
K
,
N
)
```
这里就不展开其他解法了,留在下一篇文章
[
高楼扔鸡蛋进阶
](
../动态规划系列/高楼扔鸡蛋进阶.md
)
这里就不展开其他解法了,留在下一篇文章
[
高楼扔鸡蛋进阶
](
https://labuladong.gitbook.io/algo
)
我觉得吧,我们这种解法就够了:找状态,做选择,足够清晰易懂,可流程化,可举一反三。掌握这套框架学有余力的话,再去考虑那些奇技淫巧也不迟。
...
...
数据结构系列/二叉搜索树操作集锦.md
浏览文件 @
e36b4778
...
...
@@ -310,4 +310,36 @@ void BST(TreeNode root, int target) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
dekunma
](
https://www.linkedin.com/in/dekun-ma-036a9b198/
)
提供第98题C++代码:
```
C++
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isValidBST(TreeNode* root) {
// 用helper method求解
return isValidBST(root, nullptr, nullptr);
}
bool isValidBST(TreeNode* root, TreeNode* min, TreeNode* max) {
// base case, root为nullptr
if (!root) return true;
// 不符合BST的条件
if (min && root->val <= min->val) return false;
if (max && root->val >= max->val) return false;
// 向左右子树分别递归求解
return isValidBST(root->left, min, root)
&& isValidBST(root->right, root, max);
}
};
```
算法思维系列/双指针技巧.md
浏览文件 @
e36b4778
...
...
@@ -230,4 +230,25 @@ void reverse(int[] nums) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
ryandeng32
](
https://github.com/ryandeng32/
)
提供 Python 代码
```
python
class
Solution
:
def
hasCycle
(
self
,
head
:
ListNode
)
->
bool
:
# 检查链表头是否为None,是的话则不可能为环形
if
head
is
None
:
return
False
# 快慢指针初始化
slow
=
fast
=
head
# 若链表非环形则快指针终究会遇到None,然后退出循环
while
fast
.
next
and
fast
.
next
.
next
:
# 更新快慢指针
slow
=
slow
.
next
fast
=
fast
.
next
.
next
# 快指针追上慢指针则链表为环形
if
slow
==
fast
:
return
True
# 退出循环,则链表有结束,不可能为环形
return
False
```
算法思维系列/滑动窗口技巧.md
浏览文件 @
e36b4778
...
...
@@ -12,8 +12,8 @@
**最新消息:关注公众号参与活动,有机会成为 [70k star 算法仓库](https://github.com/labuladong/fucking-algorithm) 的贡献者,机不可失时不再来**
!
相关推荐:
*
[
东哥吃葡萄时竟然吃出一道算法题!
](
../高频面试系列/吃葡萄.md
)
*
[
如何寻找缺失的元素
](
../高频面试系列/消失的元素.md
)
*
[
东哥吃葡萄时竟然吃出一道算法题!
](
https://labuladong.gitbook.io/algo
)
*
[
如何寻找缺失的元素
](
https://labuladong.gitbook.io/algo
)
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
...
...
高频面试系列/LRU算法.md
浏览文件 @
e36b4778
...
...
@@ -432,4 +432,35 @@ class LRUCache {
node
*
head
,
*
tail
;
};
```
```
```
python3
"""
所谓LRU缓存,根本的难点在于记录最久被使用的键值对,这就设计到排序的问题,
在python中,天生具备排序功能的字典就是OrderDict。
注意到,记录最久未被使用的键值对的充要条件是将每一次put/get的键值对都定义为
最近访问,那么最久未被使用的键值对自然就会排到最后。
如果你深入python OrderDict的底层实现,就会知道它的本质是个双向链表+字典。
它内置支持了
1. move_to_end来重排链表顺序,它可以让我们将最近访问的键值对放到最后面
2. popitem来弹出键值对,它既可以弹出最近的,也可以弹出最远的,弹出最远的就是我们要的操作。
"""
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity # cache的容量
self.visited = OrderedDict() # python内置的OrderDict具备排序的功能
def get(self, key: int) -> int:
if key not in self.visited:
return -1
self.visited.move_to_end(key) # 最近访问的放到链表最后,维护好顺序
return self.visited[key]
def put(self, key: int, value: int) -> None:
if key not in self.visited and len(self.visited) == self.capacity:
# last=False时,按照FIFO顺序弹出键值对
# 因为我们将最近访问的放到最后,所以最远访问的就是最前的,也就是最first的,故要用FIFO顺序
self.visited.popitem(last=False)
self.visited[key]=value
self.visited.move_to_end(key) # 最近访问的放到链表最后,维护好顺序
```
高频面试系列/合法括号判定.md
浏览文件 @
e36b4778
...
...
@@ -112,4 +112,28 @@ char leftOf(char c) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
```
java
//基本思想:每次遇到左括号时都将相对应的右括号')',']'或'}'推入堆栈
//如果在字符串中出现右括号,则需要检查堆栈是否为空,以及顶部元素是否与该右括号相同。如果不是,则该字符串无效。
//最后,我们还需要检查堆栈是否为空
public
boolean
isValid
(
String
s
)
{
Deque
<
Character
>
stack
=
new
ArrayDeque
<>();
for
(
char
c
:
s
.
toCharArray
()){
//是左括号就将相对应的右括号入栈
if
(
c
==
'('
)
{
stack
.
offerLast
(
')'
);
}
else
if
(
c
==
'{'
){
stack
.
offerLast
(
'}'
);
}
else
if
(
c
==
'['
){
stack
.
offerLast
(
']'
);
}
else
if
(
stack
.
isEmpty
()
||
stack
.
pollLast
()!=
c
){
//出现右括号,检查堆栈是否为空,以及顶部元素是否与该右括号相同
return
false
;
}
}
return
stack
.
isEmpty
();
}
```
高频面试系列/打印素数.md
浏览文件 @
e36b4778
...
...
@@ -178,4 +178,41 @@ int countPrimes(int n) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
C++解法:
采用的算法是埃拉托斯特尼筛法
埃拉托斯特尼筛法的具体内容就是:
**要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。**
同时考虑到大于2的偶数都不是素数,所以可以进一步优化成:
**要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的奇数倍剔除,剩下的奇数就是素数。**
此算法其实就是上面的Java解法所采用的。
这里提供C++的代码:
```
C++
class Solution {
public:
int countPrimes(int n) {
int res = 0;
bool prime[n+1];
for(int i = 0; i < n; ++i)
prime[i] = true;
for(int i = 2; i <= sqrt(n); ++i) //计数过程
{ //外循环优化,因为判断一个数是否为质数只需要整除到sqrt(n),反推亦然
if(prime[i])
{
for(int j = i * i; j < n; j += i) //内循环优化,i*i之前的比如i*2,i*3等,在之前的循环中已经验证了
{
prime[j] = false;
}
}
}
for (int i = 2; i < n; ++i)
if (prime[i]) res++; //最后遍历统计一遍,存入res
return res;
}
};
```
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录