Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
coolalex776
Fucking Algorithm
提交
b09dc336
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,发现更多精彩内容 >>
未验证
提交
b09dc336
编写于
3月 13, 2021
作者:
B
BruceCat
提交者:
GitHub
3月 13, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into pr-496
上级
7fda8faf
1746166c
变更
21
隐藏空白更改
内联
并排
Showing
21 changed file
with
1228 addition
and
41 deletion
+1228
-41
动态规划系列/动态规划之KMP字符匹配算法.md
动态规划系列/动态规划之KMP字符匹配算法.md
+37
-2
动态规划系列/编辑距离.md
动态规划系列/编辑距离.md
+29
-2
动态规划系列/贪心算法之区间调度问题.md
动态规划系列/贪心算法之区间调度问题.md
+42
-3
数据结构系列/二叉搜索树操作集锦.md
数据结构系列/二叉搜索树操作集锦.md
+111
-4
数据结构系列/单调栈.md
数据结构系列/单调栈.md
+24
-0
数据结构系列/单调队列.md
数据结构系列/单调队列.md
+102
-2
数据结构系列/设计Twitter.md
数据结构系列/设计Twitter.md
+119
-2
数据结构系列/递归反转链表的一部分.md
数据结构系列/递归反转链表的一部分.md
+37
-2
算法思维系列/UnionFind算法应用.md
算法思维系列/UnionFind算法应用.md
+77
-2
算法思维系列/区间调度问题之区间合并.md
算法思维系列/区间调度问题之区间合并.md
+62
-2
算法思维系列/字符串乘法.md
算法思维系列/字符串乘法.md
+78
-2
算法思维系列/滑动窗口技巧.md
算法思维系列/滑动窗口技巧.md
+28
-2
算法思维系列/烧饼排序.md
算法思维系列/烧饼排序.md
+71
-2
高频面试系列/LRU算法.md
高频面试系列/LRU算法.md
+87
-0
高频面试系列/koko偷香蕉.md
高频面试系列/koko偷香蕉.md
+78
-2
高频面试系列/二分查找判定子序列.md
高频面试系列/二分查找判定子序列.md
+64
-2
高频面试系列/判断回文链表.md
高频面试系列/判断回文链表.md
+32
-2
高频面试系列/子集排列组合.md
高频面试系列/子集排列组合.md
+39
-2
高频面试系列/最长回文子串.md
高频面试系列/最长回文子串.md
+37
-2
高频面试系列/消失的元素.md
高频面试系列/消失的元素.md
+47
-2
高频面试系列/缺失和重复的元素.md
高频面试系列/缺失和重复的元素.md
+27
-2
未找到文件。
动态规划系列/动态规划之KMP字符匹配算法.md
浏览文件 @
b09dc336
...
...
@@ -431,4 +431,40 @@ KMP 算法也就是动态规划那点事,我们的公众号文章目录有一
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
MoguCloud
](
https://github.com/MoguCloud
)
提供 实现 strStr() 的 Python 完整代码:
```
py
class
Solution
:
def
strStr
(
self
,
haystack
:
str
,
needle
:
str
)
->
int
:
# 边界条件判断
if
not
needle
:
return
0
pat
=
needle
txt
=
haystack
M
=
len
(
pat
)
# dp[状态][字符] = 下个状态
dp
=
[[
0
for
_
in
range
(
256
)]
for
_
in
pat
]
# base case
dp
[
0
][
ord
(
pat
[
0
])]
=
1
# 影子状态 X 初始化为 0
X
=
0
for
j
in
range
(
1
,
M
):
for
c
in
range
(
256
):
dp
[
j
][
c
]
=
dp
[
X
][
c
]
dp
[
j
][
ord
(
pat
[
j
])]
=
j
+
1
# 更新影子状态
X
=
dp
[
X
][
ord
(
pat
[
j
])]
N
=
len
(
txt
)
# pat 初始状态为 0
j
=
0
for
i
in
range
(
N
):
# 计算 pat 的下一个状态
j
=
dp
[
j
][
ord
(
txt
[
i
])]
# 到达终止态,返回结果
if
j
==
M
:
return
i
-
M
+
1
# 没到达终止态,匹配失败
return
-
1
```
动态规划系列/编辑距离.md
浏览文件 @
b09dc336
...
...
@@ -291,4 +291,31 @@ class Node {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
ChenjieXu
](
https://github.com/ChenjieXu
)
提供Python版本代码:
```
python3
def minDistance(word1, word2):
m, n = len(word1), len(word2)
# 创建 DP 数组
dp = [[0] * (n + 1) for _ in range(m + 1)]
# base case初始化
for i in range(m + 1):
dp[i][0] = i
for j in range(n + 1):
dp[0][j] = j
# 自底向上求解
for i in range(1, m + 1):
for j in range(1, n + 1):
# 状态转移方程
if word1[i - 1] == word2[j - 1]:
dp[i][j] = dp[i - 1][j - 1]
else:
dp[i][j] = min(dp[i - 1][j] + 1,
dp[i][j - 1] + 1,
dp[i - 1][j - 1] + 1)
# 储存着整个 word1 和 word2 的最小编辑距离
return dp[m][n]
```
`
\ No newline at end of file
动态规划系列/贪心算法之区间调度问题.md
浏览文件 @
b09dc336
# 贪心算法之区间调度问题
# 贪心算法之区间调度问题
<p
align=
'center'
>
...
...
@@ -158,4 +158,43 @@ int findMinArrowShots(int[][] intvs) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
### python
Edwenc 提供 第435题的python3 代码:
```
python
class
Solution
:
def
eraseOverlapIntervals
(
self
,
intervals
:
List
[
List
[
int
]])
->
int
:
### 思路是首先找到不重叠的区间的个数
### 然后再用总个数减去不重叠个数
### 获得的就是 需要移除的个数
# 首先获得区间的个数 为0的话就不用移除
n
=
len
(
intervals
)
if
n
==
0
:
return
0
# 按照每个区间的右端点值进行排序
sorted_list
=
sorted
(
intervals
,
key
=
lambda
x
:
x
[
1
]
)
# 不重叠区间个数至少是1
count
=
1
# end是所有不重叠的区间中 最大的右端点
# end的初始值即是sorted_list[0]的右端点
end
=
sorted_list
[
0
][
1
]
# 从1开始往后找 因为0在上面已经取过了
for
i
in
range
(
1
,
n
):
# start是当前区间左端点值
start
=
sorted_list
[
i
][
0
]
# 如果当前左端点比最大右端点都大了(可能相等)
# 说明两区间不重叠 count+1 再更新end
if
start
>=
end
:
count
+=
1
end
=
sorted_list
[
i
][
1
]
# 最后返回的是 需要移除的区间个数
return
n
-
count
```
\ No newline at end of file
数据结构系列/二叉搜索树操作集锦.md
浏览文件 @
b09dc336
# 二叉搜索树操作集锦
# 二叉搜索树操作集锦
<p
align=
'center'
>
...
...
@@ -310,9 +310,13 @@ void BST(TreeNode root, int target) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
[
dekunma
](
https://www.linkedin.com/in/dekun-ma-036a9b198/
)
提供第98题C++代码:
```
C++
======其他语言代码======
### c++
[
dekunma
](
https://www.linkedin.com/in/dekun-ma-036a9b198/
)
提供第98题C++代码:
```
c++
/**
* Definition for a binary tree node.
* struct TreeNode {
...
...
@@ -343,3 +347,105 @@ public:
}
};
```
### python
[
ChenjieXu
](
https://github.com/ChenjieXu
)
提供第98题Python3代码:
```
python
def
isValidBST
(
self
,
root
):
# 递归函数
def
helper
(
node
,
lower
=
float
(
'-inf'
),
upper
=
float
(
'inf'
)):
if
not
node
:
return
True
val
=
node
.
val
if
val
<=
lower
or
val
>=
upper
:
return
False
# 右节点
if
not
helper
(
node
.
right
,
val
,
upper
):
return
False
# 左节点
if
not
helper
(
node
.
left
,
lower
,
val
):
return
False
return
True
return
helper
(
root
)
```
[
lixiandea
](
https://github.com/lixiandea
)
提供第100题Python3代码:
```
python
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class
Solution
:
def
isSameTree
(
self
,
p
:
TreeNode
,
q
:
TreeNode
)
->
bool
:
'''
当前节点值相等且树的子树相等,则树相等。
递归退出条件:两个节点存在一个节点为空
'''
if
p
==
None
:
if
q
==
None
:
return
True
else
:
return
False
if
q
==
None
:
return
False
# 当前节点相同且左子树和右子树分别相同
return
p
.
val
==
q
.
val
and
self
.
isSameTree
(
p
.
left
,
q
.
left
)
and
self
.
isSameTree
(
p
.
right
,
q
.
right
)
```
[
Edwenc
](
https://github.com/Edwenc
)
提供 leetcode第450题的python3 代码:
```
python
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class
Solution
:
def
deleteNode
(
self
,
root
:
TreeNode
,
key
:
int
)
->
TreeNode
:
# 如果没有树 直接返回None
if
root
==
None
:
return
None
# 如果要删除的结点 就是当前结点
if
root
.
val
==
key
:
# 左子树为空 只有右子树需要被更新 直接返回
if
root
.
left
==
None
:
return
root
.
right
# 右子树为空 只有左子树需要被更新 直接返回
if
root
.
right
==
None
:
return
root
.
left
# 找出此结点左子树的最大值
# 用这个最大值 来代替当前结点
# 再在左子树中递归地删除这个最大值结点
big
=
self
.
getMax
(
root
.
left
)
root
.
val
=
big
.
val
root
.
left
=
self
.
deleteNode
(
root
.
left
,
big
.
val
)
# 当前结点较大 它的左子树中需要删除节点 递归到左子树
elif
root
.
val
>
key
:
root
.
left
=
self
.
deleteNode
(
root
.
left
,
key
)
# 当前结点较小 它的右子树中需要删除节点 递归到右子树
else
:
root
.
right
=
self
.
deleteNode
(
root
.
right
,
key
)
return
root
# 辅助函数
# 功能是找出此二叉搜索树中最大元素的结点 并返回此结点
def
getMax
(
self
,
node
):
# 一直找它的右子树 直到为空
while
node
.
right
:
node
=
node
.
right
return
node
```
\ No newline at end of file
数据结构系列/单调栈.md
浏览文件 @
b09dc336
...
...
@@ -183,6 +183,8 @@ vector<int> nextGreaterElements(vector<int>& nums) {
======其他语言代码======
### java
[
ZakAnun
](
https://github.com/ZakAnun
)
提供代码
```
java
...
...
@@ -235,4 +237,25 @@ public int[] nextGreaterElement(int[] nums1, int[] nums2) {
}
return
result
;
}
```
```
java
// 739. Daily Temperatures
class
Solution
{
public
int
[]
dailyTemperatures
(
int
[]
T
)
{
Stack
<
Integer
>
stack
=
new
Stack
<>();
int
[]
ans
=
new
int
[
T
.
length
];
for
(
int
i
=
0
;
i
<
T
.
length
;
i
++)
{
// 如果压栈之后不满足单调递减,弹出元素,直至保持单调性
while
(!
stack
.
isEmpty
()
&&
T
[
i
]
>
T
[
stack
.
peek
()])
{
int
index
=
stack
.
pop
();
// 被弹出的元素(T[index])都是小于当前的元素(T[i]),由于栈内元素单调递减,大于被弹出元素(index)的最近的就是当前元素(i)
ans
[
index
]
=
i
-
index
;
}
stack
.
push
(
i
);
}
return
ans
;
}
}
```
\ No newline at end of file
数据结构系列/单调队列.md
浏览文件 @
b09dc336
...
...
@@ -210,4 +210,105 @@ vector<int> maxSlidingWindow(vector<int>& nums, int k) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
### python3
由
[
SCUHZS
](
ttps://github.com/brucecat
)
提供
```
python
from
collections
import
deque
class
MonotonicQueue
(
object
):
def
__init__
(
self
):
# 双端队列
self
.
data
=
deque
()
def
push
(
self
,
n
):
# 实现单调队列的push方法
while
self
.
data
and
self
.
data
[
-
1
]
<
n
:
self
.
data
.
pop
()
self
.
data
.
append
(
n
)
def
max
(
self
):
# 取得单调队列中的最大值
return
self
.
data
[
0
]
def
pop
(
self
,
n
):
# 实现单调队列的pop方法
if
self
.
data
and
self
.
data
[
0
]
==
n
:
self
.
data
.
popleft
()
class
Solution
:
def
maxSlidingWindow
(
self
,
nums
:
List
[
int
],
k
:
int
)
->
List
[
int
]:
# 单调队列实现的窗口
window
=
MonotonicQueue
()
# 结果
res
=
[]
for
i
in
range
(
0
,
len
(
nums
)):
if
i
<
k
-
1
:
# 先填满窗口前k-1
window
.
push
(
nums
[
i
])
else
:
# 窗口向前滑动
window
.
push
(
nums
[
i
])
res
.
append
(
window
.
max
())
window
.
pop
(
nums
[
i
-
k
+
1
])
return
res
```
### java
```
java
class
Solution
{
public
int
[]
maxSlidingWindow
(
int
[]
nums
,
int
k
)
{
int
len
=
nums
.
length
;
// 判断数组或者窗口长度为0的情况
if
(
len
*
k
==
0
)
{
return
new
int
[
0
];
}
/*
采用两端扫描的方法
将数组分成大小为 k 的若干个窗口, 对每个窗口分别从左往右和从右往左扫描, 记录扫描的最大值
left[] 记录从左往右扫描的最大值
right[] 记录从右往左扫描的最大值
*/
int
[]
left
=
new
int
[
len
];
int
[]
right
=
new
int
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
=
i
+
k
)
{
// 每个窗口中的第一个值
left
[
i
]
=
nums
[
i
];
// 窗口的最后边界
int
index
=
i
+
k
-
1
>=
len
?
len
-
1
:
i
+
k
-
1
;
// 每个窗口的最后一个值
right
[
index
]
=
nums
[
index
];
// 对该窗口从左往右扫描
for
(
int
j
=
i
+
1
;
j
<=
index
;
j
++)
{
left
[
j
]
=
Math
.
max
(
left
[
j
-
1
],
nums
[
j
]);
}
// 对该窗口从右往左扫描
for
(
int
j
=
index
-
1
;
j
>=
i
;
j
--)
{
right
[
j
]
=
Math
.
max
(
right
[
j
+
1
],
nums
[
j
]);
}
}
int
[]
arr
=
new
int
[
len
-
k
+
1
];
// 对于第 i 个位置, 它一定是该窗口从右往左扫描数组中的最后一个值, 相对的 i + k - 1 是该窗口从左向右扫描数组中的最后一个位置
// 对两者取最大值即可
for
(
int
i
=
0
;
i
<
len
-
k
+
1
;
i
++)
{
arr
[
i
]
=
Math
.
max
(
right
[
i
],
left
[
i
+
k
-
1
]);
}
return
arr
;
}
}
```
数据结构系列/设计Twitter.md
浏览文件 @
b09dc336
...
...
@@ -302,4 +302,121 @@ PS:本文前两张图片和 GIF 是我第一次尝试用平板的绘图软件
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
happy-yuxuan
](
https://github.com/happy-yuxuan
)
提供 C++ 代码:
```
c++
static
int
timestamp
=
0
;
class
Tweet
{
private:
int
id
;
int
time
;
public:
Tweet
*
next
;
// id为推文内容,time为发文时间
Tweet
(
int
id
,
int
time
)
{
this
->
id
=
id
;
this
->
time
=
time
;
next
=
nullptr
;
}
int
getId
()
const
{
return
this
->
id
;
}
int
getTime
()
const
{
return
this
->
time
;
}
};
class
User
{
private:
int
id
;
public:
Tweet
*
head
;
// 发布的Twitter,用链表表示
unordered_set
<
int
>
followed
;
// 用户关注了那些人
User
(
int
userId
)
{
this
->
id
=
userId
;
head
=
nullptr
;
// 要先把自己关注了
followed
.
insert
(
id
);
}
void
follow
(
int
userId
)
{
followed
.
insert
(
userId
);
}
void
unfollow
(
int
userId
)
{
// 不可以取关自己
if
(
userId
!=
this
->
id
)
followed
.
erase
(
userId
);
}
void
post
(
int
contentId
)
{
Tweet
*
twt
=
new
Tweet
(
contentId
,
timestamp
);
timestamp
++
;
// 将新建的推文插入链表头
// 越靠前的推文 timestamp 值越大
twt
->
next
=
head
;
head
=
twt
;
}
};
class
Twitter
{
private:
// 映射将 userId 和 User 对象对应起来
unordered_map
<
int
,
User
*>
userMap
;
// 判断该用户存不存在系统中,即userMap中存不存在id
inline
bool
contain
(
int
id
)
{
return
userMap
.
find
(
id
)
!=
userMap
.
end
();
}
public:
Twitter
()
{
userMap
.
clear
();
}
/* user 发表一条 tweet 动态 */
void
postTweet
(
int
userId
,
int
tweetId
)
{
if
(
!
contain
(
userId
))
userMap
[
userId
]
=
new
User
(
userId
);
userMap
[
userId
]
->
post
(
tweetId
);
}
/* 返回该 user 关注的人(包括他自己)最近的动态 id,
最多 10 条,而且这些动态必须按从新到旧的时间线顺序排列。*/
vector
<
int
>
getNewsFeed
(
int
userId
)
{
vector
<
int
>
ret
;
if
(
!
contain
(
userId
))
return
ret
;
// 构造一个自动通过Tweet发布的time属性从大到小排序的二叉堆
typedef
function
<
bool
(
const
Tweet
*
,
const
Tweet
*
)
>
Compare
;
Compare
cmp
=
[](
const
Tweet
*
a
,
const
Tweet
*
b
)
{
return
a
->
getTime
()
<
b
->
getTime
();
};
priority_queue
<
Tweet
*
,
vector
<
Tweet
*>
,
Compare
>
q
(
cmp
);
// 关注列表的用户Id
unordered_set
<
int
>
&
users
=
userMap
[
userId
]
->
followed
;
// 先将所有链表头节点插入优先级队列
for
(
int
id
:
users
)
{
if
(
!
contain
(
id
))
continue
;
Tweet
*
twt
=
userMap
[
id
]
->
head
;
if
(
twt
==
nullptr
)
continue
;
q
.
push
(
twt
);
}
while
(
!
q
.
empty
())
{
Tweet
*
t
=
q
.
top
();
q
.
pop
();
ret
.
push_back
(
t
->
getId
());
if
(
ret
.
size
()
==
10
)
return
ret
;
// 最多返回 10 条就够了
if
(
t
->
next
)
q
.
push
(
t
->
next
);
}
return
ret
;
}
/* follower 关注 followee */
void
follow
(
int
followerId
,
int
followeeId
)
{
// 若 follower 不存在,则新建
if
(
!
contain
(
followerId
))
userMap
[
followerId
]
=
new
User
(
followerId
);
// 若 followee 不存在,则新建
if
(
!
contain
(
followeeId
))
userMap
[
followeeId
]
=
new
User
(
followeeId
);
userMap
[
followerId
]
->
follow
(
followeeId
);
}
/* follower 取关 followee,如果 Id 不存在则什么都不做 */
void
unfollow
(
int
followerId
,
int
followeeId
)
{
if
(
contain
(
followerId
))
userMap
[
followerId
]
->
unfollow
(
followeeId
);
}
};
```
\ No newline at end of file
数据结构系列/递归反转链表的一部分.md
浏览文件 @
b09dc336
...
...
@@ -218,4 +218,40 @@ ListNode reverseBetween(ListNode head, int m, int n) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
DiamondI
](
https://github.com/DiamondI
)
提供python3版本代码:
思路:递归。时间复杂度为O(n),由于递归调用需要借助栈的空间,因此空间复杂度亦为O(n)。
```
python3
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def __init__(self):
self.__successor = None
def __reverseN(self, head: ListNode, n: int) -> ListNode:
if n == 1:
# 记录第 n + 1 个节点
self.__successor = head.next;
return head;
# 以 head.next 为起点,需要反转前 n - 1 个节点
last = self.__reverseN(head.next, n - 1);
head.next.next = head;
# 让反转之后的 head 节点和后面的节点连起来
head.next = self.__successor;
return last;
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
# base case
if m == 1:
return self.__reverseN(head, n);
# 前进到反转的起点触发 base case
head.next = self.reverseBetween(head.next, m - 1, n - 1);
return head;
```
算法思维系列/UnionFind算法应用.md
浏览文件 @
b09dc336
...
...
@@ -20,6 +20,8 @@
[
990.等式方程的可满足性
](
https://leetcode-cn.com/problems/surrounded-regions
)
[
261.以图判树
](
https://leetcode-cn.com/problems/graph-valid-tree/
)
**-----------**
上篇文章很多读者对于 Union-Find 算法的应用表示很感兴趣,这篇文章就拿几道 LeetCode 题目来讲讲这个算法的巧妙用法。
...
...
@@ -250,4 +252,78 @@ boolean equationsPossible(String[] equations) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
第261题的Java代码(提供:
[
LEODPEN
](
https://github.com/LEODPEN
)
)
```
java
class
Solution
{
class
DisjointSet
{
int
count
;
// 连通分量的总个数
int
[]
parent
;
// 每个节点的头节点(不一定是连通分量的最终头节点)
int
[]
size
;
// 每个连通分量的大小
public
DisjointSet
(
int
n
)
{
parent
=
new
int
[
n
];
size
=
new
int
[
n
];
// 初为n个连通分量,期望最后为1
count
=
n
;
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
// 初始的连通分量只有该节点本身
parent
[
i
]
=
i
;
size
[
i
]
=
1
;
}
}
/**
* @param first 节点1
* @param second 节点2
* @return 未连通 && 连通成功
*/
public
boolean
union
(
int
first
,
int
second
)
{
// 分别找到包含first 和 second 的最终根节点
int
firstParent
=
findRootParent
(
first
),
secondParent
=
findRootParent
(
second
);
// 相等说明已经处于一个连通分量,即说明有环
if
(
firstParent
==
secondParent
)
return
false
;
// 将较小的连通分量融入较大的连通分量
if
(
size
[
firstParent
]
>=
size
[
secondParent
])
{
parent
[
secondParent
]
=
firstParent
;
size
[
firstParent
]
+=
size
[
secondParent
];
}
else
{
parent
[
firstParent
]
=
secondParent
;
size
[
secondParent
]
+=
size
[
firstParent
];
}
// 连通分量已合并,count减少
count
--;
return
true
;
}
/**
* @param node 某节点
* @return 包含该节点的连通分量的最终根节点
*/
private
int
findRootParent
(
int
node
)
{
while
(
node
!=
parent
[
node
])
{
// 压缩路径
parent
[
node
]
=
parent
[
parent
[
node
]];
node
=
parent
[
node
];
}
return
node
;
}
}
public
boolean
validTree
(
int
n
,
int
[][]
edges
)
{
// 树的特性:节点数 = 边数 + 1
if
(
edges
.
length
!=
n
-
1
)
return
false
;
DisjointSet
djs
=
new
DisjointSet
(
n
);
for
(
int
[]
edg
:
edges
)
{
// 判断连通情况(如果合并的两个点在一个连通分量里,说明有环)
if
(!
djs
.
union
(
edg
[
0
],
edg
[
1
]))
return
false
;
}
// 是否全部节点均已相连
return
djs
.
count
==
1
;
}
}
```
算法思维系列/区间调度问题之区间合并.md
浏览文件 @
b09dc336
...
...
@@ -90,5 +90,66 @@ def merge(intervals):
<p
align=
'center'
>
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
~~~
java
class
Solution
{
/**
* 1. 先对区间集合进行排序(根据开始位置)
* 2. 合并的情况一共有三种
* a. b. c.
* |---------| |--------| |--------|
* |---------| |--| |--------|
* a和b两种情况,合并取右边界大的值,c情况不合并
*
*/
private
int
[][]
tmp
;
public
int
[][]
merge
(
int
[][]
intervals
)
{
if
(
intervals
==
null
||
intervals
.
length
==
0
)
return
new
int
[
0
][
0
];
int
length
=
intervals
.
length
;
//将列表中的区间按照左端点升序排序
// Arrays.sort(intervals,(v1,v2) -> v1[0]-v2[0]);
this
.
tmp
=
new
int
[
length
][
2
];
sort
(
intervals
,
0
,
length
-
1
);
int
[][]
ans
=
new
int
[
length
][
2
];
int
index
=
-
1
;
for
(
int
[]
interval:
intervals
){
// 当结果数组是空是,或者当前区间的起始位置 > 结果数组中最后区间的终止位置(即上图情况c);
// 则不合并,直接将当前区间加入结果数组。
if
(
index
==
-
1
||
interval
[
0
]
>
ans
[
index
][
1
]){
ans
[++
index
]
=
interval
;
}
else
{
// 反之将当前区间合并至结果数组的最后区间(即上图情况a,b)
ans
[
index
][
1
]
=
Math
.
max
(
ans
[
index
][
1
],
interval
[
1
]);
}
}
return
Arrays
.
copyOf
(
ans
,
index
+
1
);
}
//归并排序
public
void
sort
(
int
[][]
intervals
,
int
l
,
int
r
){
if
(
l
>=
r
)
return
;
int
mid
=
l
+
(
r
-
l
)/
2
;
sort
(
intervals
,
l
,
mid
);
sort
(
intervals
,
mid
+
1
,
r
);
//合并
int
i
=
l
,
j
=
mid
+
1
;
for
(
int
k
=
l
;
k
<=
r
;
k
++){
if
(
i
>
mid
)
tmp
[
k
]=
intervals
[
j
++];
else
if
(
j
>
r
)
tmp
[
k
]=
intervals
[
i
++];
else
if
(
intervals
[
i
][
0
]>
intervals
[
j
][
0
])
tmp
[
k
]
=
intervals
[
j
++];
else
tmp
[
k
]
=
intervals
[
i
++];
}
System
.
arraycopy
(
tmp
,
l
,
intervals
,
l
,
r
-
l
+
1
);
}
}
~~~
======其他语言代码======
\ No newline at end of file
算法思维系列/字符串乘法.md
浏览文件 @
b09dc336
...
...
@@ -101,4 +101,80 @@ string multiply(string num1, string num2) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
### python
[
fengshuu
](
https://github.com/fengshuu
)
提供 Python 解法代码:
```
python
def
multiply
(
num1
:
str
,
num2
:
str
)
->
str
:
m
,
n
=
len
(
num1
),
len
(
num2
)
# 结果最多为 m + n 位数
res
=
[
0
]
*
(
m
+
n
)
# 从个位数开始逐位相乘
for
i
in
range
(
m
-
1
,
-
1
,
-
1
):
for
j
in
range
(
n
-
1
,
-
1
,
-
1
):
mul
=
int
(
num1
[
i
])
*
int
(
num2
[
j
])
# 乘积在 res 对应的索引位置
p1
=
i
+
j
p2
=
i
+
j
+
1
# 叠加到 res 上
digit_sum
=
mul
+
res
[
p2
]
res
[
p2
]
=
digit_sum
%
10
res
[
p1
]
+=
digit_sum
//
10
# 结果前缀可能存的 0(未使用的位)
i
=
0
while
i
<
len
(
res
)
and
res
[
i
]
==
0
:
i
+=
1
# 将计算结果转化成字符串
result_str
=
""
.
join
(
str
(
x
)
for
x
in
res
[
i
:])
return
"0"
if
len
(
result_str
)
==
0
else
result_str
```
### java
[
Zane Wang
](
https://github.com/zanecat
)
提供 Java 解法代码:
```
java
public
String
multiply
(
String
num1
,
String
num2
)
{
// 初始化字符数组
char
[]
s1
=
num1
.
toCharArray
();
char
[]
s2
=
num2
.
toCharArray
();
// 结果长度最多为两字符串长度之和
int
[]
res
=
new
int
[
s1
.
length
+
s2
.
length
];
// 从个位开始遍历,把两数字中每一位相乘
for
(
int
i
=
s1
.
length
-
1
;
i
>=
0
;
i
--)
{
for
(
int
j
=
s2
.
length
-
1
;
j
>=
0
;
j
--)
{
// 计算乘积,并把乘积放在 res 对应的位置, 暂时不考虑进位
res
[
i
+
j
+
1
]
+=
(
s1
[
i
]
-
'0'
)
*
(
s2
[
j
]
-
'0'
);
}
}
// 从个位再次遍历,如果上一次遍历中两数乘积为两位数,进位并叠加到前面一位
int
carry
=
0
;
for
(
int
i
=
res
.
length
-
1
;
i
>=
0
;
i
--)
{
int
sum
=
res
[
i
]
+
carry
;
res
[
i
]
=
sum
%
10
;
carry
=
sum
/
10
;
}
//遍历res数组,构造最终答案字符串
StringBuilder
ans
=
new
StringBuilder
();
int
i
=
0
;
// 首先找到不为0的第一位
while
(
i
<
res
.
length
-
1
&&
res
[
i
]
==
0
)
{
i
++;
}
// 将后面的数字附加到ans后面
while
(
i
<
res
.
length
)
{
ans
.
append
(
res
[
i
++]);
}
return
ans
.
toString
();
}
```
\ No newline at end of file
算法思维系列/滑动窗口技巧.md
浏览文件 @
b09dc336
...
...
@@ -371,4 +371,31 @@ class Solution:
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
第3题 Python3 代码(提供:
[
FaDrYL
](
https://github.com/FaDrYL
)
):
```
Python3
def lengthOfLongestSubstring(self, s: str) -> int:
# 子字符串
sub = ""
largest = 0
# 循环字符串,将当前字符加入子字符串,并检查长度
for i in range(len(s)):
if s[i] not in sub:
# 当前字符不存在于子字符串中,加入当前字符
sub += s[i]
else:
# 如果当前子字符串的长度超过了之前的记录
if len(sub) > largest:
largest = len(sub)
# 将子字符串从当前字符处+1切片至最后,并加入当前字符
sub = sub[sub.find(s[i])+1:] + s[i]
# 如果最后的子字符串长度超过了之前的记录
if len(sub) > largest:
return len(sub)
return largest
```
算法思维系列/烧饼排序.md
浏览文件 @
b09dc336
...
...
@@ -149,4 +149,74 @@ void reverse(int[] arr, int i, int j) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
L-WEIWEI
](
https://github.com/L-WWEEII
)
提供 第969题的 Java 代码:
```
java
class
Solution
{
public
List
<
Integer
>
pancakeSort
(
int
[]
A
)
{
List
<
Integer
>
ans
=
new
ArrayList
<
Integer
>();
int
len
=
A
.
length
;
if
(
len
==
0
){
return
ans
;
}
// maxIndex[0] == 当前轮次的最大元素, maxIndex[1] == 最大元素下标
int
[]
maxIndex
=
new
int
[
2
];
maxIndex
[
0
]
=
Integer
.
MIN_VALUE
;
int
maxCount
=
0
;
// maxCount == len 时,说明完成了整个数组的最大值沉底操作,
while
(
maxCount
<
len
-
1
){
maxCount
=
maxValueDown
(
A
,
maxIndex
,
maxCount
,
ans
);
// 每做完一次最大值沉底操作,初始化最大元素值
maxIndex
[
0
]
=
Integer
.
MIN_VALUE
;
}
return
ans
;
}
public
int
maxValueDown
(
int
[]
A
,
int
[]
maxIndex
,
int
maxCount
,
List
<
Integer
>
ans
){
// 遍历条件为 i < A.length - maxCount , 每次最大值沉底时,maxCount + 1,因此下次遍历即可不对最后 maxCount 个元素做操作
for
(
int
i
=
0
;
i
<
A
.
length
-
maxCount
;
i
++){
// 元素大于当前储存的元素时,将值与下标 copy 到 maxIndex 数组中
if
(
A
[
i
]
>
maxIndex
[
0
]){
maxIndex
[
0
]
=
A
[
i
];
maxIndex
[
1
]
=
i
;
}
}
// 如果当前轮次最大元素的下标的下一位是上一轮次的最大下标,则不做翻转操作,直接返回 maxCount + 1
if
(
maxIndex
[
1
]
+
1
==
A
.
length
-
maxCount
){
return
maxCount
+
1
;
}
// 使用最大值沉底时,当本轮最大值在首位时,不需要再将其先翻转至首位,所以不添加
if
(
maxIndex
[
1
]
>
0
){
// 将该轮次要翻转的下标添加到结果集中,结果集中需要的是翻转的位置而不是下标,所以添加时下标得 + 1
ans
.
add
(
maxIndex
[
1
]
+
1
);
}
// 双指针原地交换数组中的值
// 左指针指0
int
left
=
0
;
// 右指针指向当前轮次最大元素的下标
int
right
=
maxIndex
[
1
];
while
(
left
<
right
){
// 交换元素值
A
[
left
]
+=
A
[
right
];
A
[
right
]
=
A
[
left
]
-
A
[
right
];
A
[
left
]
-=
A
[
right
];
left
++;
right
--;
}
// 上面交换玩元素值后,当前轮次最大元素排在首位,再从上一轮次最大元素 - 1 的位置翻转
// 则当前轮次的最大元素成功沉底
ans
.
add
(
A
.
length
-
maxCount
);
left
=
0
;
right
=
A
.
length
-
1
-
maxCount
;
while
(
left
<
right
){
A
[
left
]
+=
A
[
right
];
A
[
right
]
=
A
[
left
]
-
A
[
right
];
A
[
left
]
-=
A
[
right
];
left
++;
right
--;
}
return
maxCount
+
1
;
}
}
```
高频面试系列/LRU算法.md
浏览文件 @
b09dc336
...
...
@@ -347,6 +347,93 @@ class LRUCache {
</p>
======其他语言代码======
[
gowufang
](
https://github.com/gowufang
)
提供第146题C++代码:
```
cpp
class
LRUCache
{
public:
struct
node
{
int
val
;
int
key
;
node
*
pre
;
//当前节点的前一个节点
node
*
next
;
//当前节点的后一个节点
node
(){}
node
(
int
key
,
int
val
)
:
key
(
key
),
val
(
val
),
pre
(
NULL
),
next
(
NULL
){}
};
LRUCache
(
int
size
)
{
this
->
size
=
size
;
head
=
new
node
();
tail
=
new
node
();
head
->
next
=
tail
;
tail
->
pre
=
head
;
}
void
movetohead
(
node
*
cur
)
//相当于一个insert操作,在head 和 head的next之间插入一个节点
{
node
*
next
=
head
->
next
;
//head的next先保存起来
head
->
next
=
cur
;
//将当前节点移动到head的后面
cur
->
pre
=
head
;
//当前节点cur的pre指向head
next
->
pre
=
cur
;
cur
->
next
=
next
;
}
node
*
deletecurrentnode
(
node
*
cur
)
//移除当前节点
{
cur
->
pre
->
next
=
cur
->
next
;
cur
->
next
->
pre
=
cur
->
pre
;
return
cur
;
}
void
makerecently
(
node
*
cur
)
{
node
*
temp
=
deletecurrentnode
(
cur
);
// 删除 cur,要重新插入到对头
movetohead
(
temp
);
//cur放到队头去
}
int
get
(
int
key
)
{
int
ret
=
-
1
;
if
(
map
.
count
(
key
))
{
node
*
temp
=
map
[
key
];
makerecently
(
temp
);
// 将 key 变为最近使用
ret
=
temp
->
val
;
}
return
ret
;
}
void
put
(
int
key
,
int
value
)
{
if
(
map
.
count
(
key
))
{
// 修改 key 的值
node
*
temp
=
map
[
key
];
temp
->
val
=
value
;
// 将 key 变为最近使用
makerecently
(
temp
);
}
else
{
node
*
cur
=
new
node
(
key
,
value
);
if
(
map
.
size
()
==
size
)
{
// 链表头部就是最久未使用的 key
node
*
temp
=
deletecurrentnode
(
tail
->
pre
);
map
.
erase
(
temp
->
key
);
}
movetohead
(
cur
);
map
[
key
]
=
cur
;
}
}
unordered_map
<
int
,
node
*>
map
;
int
size
;
node
*
head
,
*
tail
;
};
```
```
python3
"""
所谓LRU缓存,根本的难点在于记录最久被使用的键值对,这就设计到排序的问题,
...
...
高频面试系列/koko偷香蕉.md
浏览文件 @
b09dc336
...
...
@@ -169,4 +169,81 @@ for (int i = 0; i < n; i++)
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
#### c++
[
cchroot
](
https://github.com/cchroot
)
提供 C++ 代码:
```
c++
class
Solution
{
public:
int
minEatingSpeed
(
vector
<
int
>&
piles
,
int
H
)
{
// 二分法查找最小速度
// 初始化最小速度为 1,最大速度为题目设定的最大值 10^9
// 这里也可以遍历 piles 数组,获取数组中的最大值,设置 right 为数组中的最大值即可(因为每堆香蕉1小时吃完是最快的)
// log2(10^9) 约等于30,次数不多,所以这里暂时就不采取遍历获取最大值了
int
left
=
1
,
right
=
pow
(
10
,
9
);
while
(
left
<
right
)
{
// 二分法基本的防止溢出
int
mid
=
left
+
(
right
-
left
)
/
2
;
// 以 mid 的速度吃香蕉,是否能在 H 小时内吃完香蕉
if
(
!
canFinish
(
piles
,
mid
,
H
))
left
=
mid
+
1
;
else
right
=
mid
;
}
return
left
;
}
// 以 speed 的速度是否能把香蕉吃完
bool
canFinish
(
vector
<
int
>&
piles
,
int
speed
,
int
H
)
{
int
time
=
0
;
// 遍历累加时间 time
for
(
int
p
:
piles
)
time
+=
(
p
-
1
)
/
speed
+
1
;
return
time
<=
H
;
// time 小于等于 H 说明能在 H 小时吃完返回 true, 否则返回 false
}
};
```
### python
[
tonytang731
](
https://https://github.com/tonytang731
)
提供 Python3 代码:
```
python
import
math
class
Solution
:
def
minEatingSpeed
(
self
,
piles
,
H
):
# 初始化起点和终点, 最快的速度可以一次拿完最大的一堆
start
=
1
end
=
max
(
piles
)
# while loop进行二分查找
while
start
+
1
<
end
:
mid
=
start
+
(
end
-
start
)
//
2
# 如果中点所需时间大于H, 我们需要加速, 将起点设为中点
if
self
.
timeH
(
piles
,
mid
)
>
H
:
start
=
mid
# 如果中点所需时间小于H, 我们需要减速, 将终点设为中点
else
:
end
=
mid
# 提交前确认起点是否满足条件,我们要尽量慢拿
if
self
.
timeH
(
piles
,
start
)
<=
H
:
return
start
# 若起点不符合, 则中点是答案
return
end
def
timeH
(
self
,
piles
,
K
):
# 初始化时间
H
=
0
#求拿每一堆需要多长时间
for
pile
in
piles
:
H
+=
math
.
ceil
(
pile
/
K
)
return
H
```
高频面试系列/二分查找判定子序列.md
浏览文件 @
b09dc336
...
...
@@ -168,4 +168,67 @@ boolean isSubsequence(String s, String t) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
dekunma
](
https://www.linkedin.com/in/dekun-ma-036a9b198/
)
提供C++代码
**解法一:遍历(也可以用双指针):**
```
C++
class Solution {
public:
bool isSubsequence(string s, string t) {
// 遍历s
for(int i = 0; i < s.size(); i++) {
// 找到s[i]字符在t中的位置
size_t pos = t.find(s[i]);
// 如果s[i]字符不在t中,返回false
if(pos == std::string::npos) return false;
// 如果s[i]在t中,后面就只看pos以后的字串,防止重复查找
else t = t.substr(pos + 1);
}
return true;
}
};
```
**解法二:二分查找:**
```
C++
class Solution {
public:
bool isSubsequence(string s, string t) {
int m = s.size(), n = t.size();
// 对 t 进行预处理
vector<int> index[256];
for (int i = 0; i < n; i++) {
char c = t[i];
index[c].push_back(i);
}
// 串 t 上的指针
int j = 0;
// 借助 index 查找 s[i]
for (int i = 0; i < m; i++) {
char c = s[i];
// 整个 t 压根儿没有字符 c
if (index[c].empty()) return false;
int pos = left_bound(index[c], j);
// 二分搜索区间中没有找到字符 c
if (pos == index[c].size()) return false;
// 向前移动指针 j
j = index[c][pos] + 1;
}
return true;
}
// 查找左侧边界的二分查找
int left_bound(vector<int> arr, int tar) {
int lo = 0, hi = arr.size();
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (tar > arr[mid]) {
lo = mid + 1;
} else {
hi = mid;
}
}
return lo;
}
};
```
高频面试系列/判断回文链表.md
浏览文件 @
b09dc336
...
...
@@ -237,4 +237,35 @@ p.next = reverse(q);
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
C++版本:
```
cpp
bool
isPalindrome
(
ListNode
*
head
)
{
if
(
head
==
nullptr
||
head
->
next
==
nullptr
)
//为空或者只有一个节点时,直接判断为true
return
true
;
ListNode
*
slow
=
head
,
*
fast
=
head
;
while
(
fast
!=
nullptr
)
{
//首先找到中间节点
slow
=
slow
->
next
;
fast
=
fast
->
next
==
nullptr
?
fast
->
next
:
fast
->
next
->
next
;
//因为链表长度可能是奇数或偶数,所以需要进行判断
}
ListNode
*
temp
=
nullptr
,
*
pre
=
nullptr
;
//pre始终保持后续链表的头部,temp节点则作为中间零时替换的节点
while
(
slow
!=
nullptr
)
{
//利用头插法,将当前节点与后续链表断链处理,反转后半部分的链表
temp
=
slow
->
next
;
slow
->
next
=
pre
;
//建立连接
pre
=
slow
;
//pre始终作为后续链表的头部
slow
=
temp
;
}
while
(
head
!=
nullptr
&&
pre
!=
nullptr
)
{
//同步进行比较
if
(
head
->
val
!=
pre
->
val
)
{
//值有不一样的,说明不是回文联表,直接返回false了
return
false
;
}
head
=
head
->
next
;
//head向下走,直到走到空
pre
=
pre
->
next
;
//pre节点也向下走,直到走到空
}
return
true
;
//到此说明当前链表是回文链表返回true即可
}
```
高频面试系列/子集排列组合.md
浏览文件 @
b09dc336
...
...
@@ -283,5 +283,42 @@ void backtrack(int[] nums, LinkedList<Integer> track) {
<p
align=
'center'
>
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
======其他语言代码======
\ No newline at end of file
[
userLF
](
https://github.com/userLF
)
提供全排列的java代码:
```
java
import
java.util.ArrayList
;
import
java.util.List
;
class
Solution
{
List
<
List
<
Integer
>>
res
=
new
ArrayList
<>();
public
List
<
List
<
Integer
>>
permute
(
int
[]
nums
)
{
res
.
clear
();
dfs
(
nums
,
0
);
//
return
res
;
}
public
void
dfs
(
int
[]
n
,
int
start
)
{
//start表示要被替换元素的位置
if
(
start
>=
n
.
length
)
{
List
<
Integer
>
list
=
new
ArrayList
<
Integer
>();
for
(
int
i
:
n
)
{
list
.
add
(
i
);
}
res
.
add
(
list
);
return
;
}
for
(
int
i
=
start
;
i
<
n
.
length
;
i
++)
{
//i从start开始,如果从start+1开始的话,会把当前序列遗漏掉直接保存了下一个序列
int
temp
=
n
[
i
];
n
[
i
]
=
n
[
start
];
n
[
start
]
=
temp
;
dfs
(
n
,
start
+
1
);
//递归下一个位置
//回到上一个状态
n
[
start
]
=
n
[
i
];
n
[
i
]
=
temp
;
}
}
}
```
\ No newline at end of file
高频面试系列/最长回文子串.md
浏览文件 @
b09dc336
...
...
@@ -131,4 +131,40 @@ string longestPalindrome(string s) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
cchromt
](
https://github.com/cchroot
)
提供 Java 代码:
```
java
// 中心扩展算法
class
Solution
{
public
String
longestPalindrome
(
String
s
)
{
// 如果字符串长度小于2,则直接返回其本身
if
(
s
.
length
()
<
2
)
{
return
s
;
}
String
res
=
""
;
for
(
int
i
=
0
;
i
<
s
.
length
()
-
1
;
i
++)
{
// 以 s.charAt(i) 为中心的最长回文子串
String
s1
=
palindrome
(
s
,
i
,
i
);
// 以 s.charAt(i) 和 s.charAt(i+1) 为中心的最长回文子串
String
s2
=
palindrome
(
s
,
i
,
i
+
1
);
res
=
res
.
length
()
>
s1
.
length
()
?
res
:
s1
;
res
=
res
.
length
()
>
s2
.
length
()
?
res
:
s2
;
}
return
res
;
}
public
String
palindrome
(
String
s
,
int
left
,
int
right
)
{
// 索引未越界的情况下,s.charAt(left) == s.charAt(right) 则继续向两边拓展
while
(
left
>=
0
&&
right
<
s
.
length
()
&&
s
.
charAt
(
left
)
==
s
.
charAt
(
right
))
{
left
--;
right
++;
}
// 这里要注意,跳出 while 循环时,恰好满足 s.charAt(i) != s.charAt(j),因此截取的的字符串为[left+1, right-1]
return
s
.
substring
(
left
+
1
,
right
);
}
}
```
做完这题,大家可以去看看
[
647. 回文子串
](
https://leetcode-cn.com/problems/palindromic-substrings/
)
,也是类似的题目
高频面试系列/消失的元素.md
浏览文件 @
b09dc336
...
...
@@ -89,6 +89,7 @@ int missingNumber(int[] nums) {
for
(
int
x
:
nums
)
sum
+=
x
;
return
expect
-
sum
;
}
```
你看,这种解法应该是最简单的,但说实话,我自己也没想到这个解法,而且我去问了几个大佬,他们也没想到这个最简单的思路。相反,如果去问一个初中生,他也许很快就能想到。
...
...
@@ -132,4 +133,49 @@ public int missingNumber(int[] nums) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
happy-yuxuan
](
https://github.com/happy-yuxuan
)
提供 三种方法的 C++ 代码:
```
c++
// 方法:异或元素和索引
int
missingNumber
(
vector
<
int
>&
nums
)
{
int
n
=
nums
.
size
();
int
res
=
0
;
// 先和新补的索引异或一下
res
^=
n
;
// 和其他的元素、索引做异或
for
(
int
i
=
0
;
i
<
n
;
i
++
)
res
^=
i
^
nums
[
i
];
return
res
;
}
```
```
c++
// 方法:等差数列求和
int
missingNumber
(
vector
<
int
>&
nums
)
{
int
n
=
nums
.
size
();
// 公式:(首项 + 末项) * 项数 / 2
int
expect
=
(
0
+
n
)
*
(
n
+
1
)
/
2
;
int
sum
=
0
;
for
(
int
x
:
nums
)
sum
+=
x
;
return
expect
-
sum
;
}
```
```
c++
// 方法:防止整型溢出
int
missingNumber
(
vector
<
int
>&
nums
)
{
int
n
=
nums
.
size
();
int
res
=
0
;
// 新补的索引
res
+=
n
-
0
;
// 剩下索引和元素的差加起来
for
(
int
i
=
0
;
i
<
n
;
i
++
)
res
+=
i
-
nums
[
i
];
return
res
;
}
```
高频面试系列/缺失和重复的元素.md
浏览文件 @
b09dc336
...
...
@@ -139,4 +139,30 @@ vector<int> findErrorNums(vector<int>& nums) {
<img
src=
"../pictures/qrcode.jpg"
width=
200
>
</p>
======其他语言代码======
\ No newline at end of file
======其他语言代码======
[
zhuli
](
https://github.com/1097452462
"zhuli"
)
提供的Java代码:
```
java
class
Solution
{
public
int
[]
findErrorNums
(
int
[]
nums
)
{
int
n
=
nums
.
length
;
int
dup
=
-
1
;
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
// 元素是从 1 开始的
int
index
=
Math
.
abs
(
nums
[
i
])
-
1
;
// nums[index] 小于 0 则说明重复访问
if
(
nums
[
index
]
<
0
)
dup
=
Math
.
abs
(
nums
[
i
]);
else
nums
[
index
]
*=
-
1
;
}
int
missing
=
-
1
;
for
(
int
i
=
0
;
i
<
n
;
i
++)
// nums[i] 大于 0 则说明没有访问
if
(
nums
[
i
]
>
0
)
// 将索引转换成元素
missing
=
i
+
1
;
return
new
int
[]{
dup
,
missing
};
}
}
```
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录