Skip to content
Merged

merge #2125

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
09ab0e4
Update 背包理论基础01背包-1.md
jianghongcheng Jun 4, 2023
37fdbd3
Update 背包理论基础01背包-2.md
jianghongcheng Jun 4, 2023
5ab0a94
Update 0416.分割等和子集.md
jianghongcheng Jun 4, 2023
212e8f8
Update 0416.分割等和子集.md
jianghongcheng Jun 4, 2023
cb9da4f
Update 0416.分割等和子集.md
jianghongcheng Jun 4, 2023
285b6ab
Update 0416.分割等和子集.md
jianghongcheng Jun 4, 2023
980c98c
Update 1049.最后一块石头的重量II.md
jianghongcheng Jun 4, 2023
8b69827
Update 0494.目标和.md
jianghongcheng Jun 4, 2023
b9faa11
Update 0474.一和零.md
jianghongcheng Jun 4, 2023
e002075
Update 背包问题理论基础完全背包.md
jianghongcheng Jun 4, 2023
ea98e43
Update 背包问题理论基础完全背包.md
jianghongcheng Jun 4, 2023
d7eac13
Update 0377.组合总和Ⅳ.md
jianghongcheng Jun 4, 2023
93952c6
Update 0377.组合总和Ⅳ.md
jianghongcheng Jun 4, 2023
245556b
Update 0322.零钱兑换.md
jianghongcheng Jun 5, 2023
beb0a51
Update 0322.零钱兑换.md
jianghongcheng Jun 5, 2023
0964e16
Update 0322.零钱兑换.md
jianghongcheng Jun 5, 2023
87e7b9d
Update 0279.完全平方数.md
jianghongcheng Jun 5, 2023
45037ce
Update 0279.完全平方数.md
jianghongcheng Jun 5, 2023
d8c51b2
Update 0139.单词拆分.md
jianghongcheng Jun 5, 2023
de7879f
Update 0139.单词拆分.md
jianghongcheng Jun 5, 2023
bdedd2d
Update 背包问题理论基础多重背包.md
jianghongcheng Jun 5, 2023
c33556c
Update 0198.打家劫舍.md
jianghongcheng Jun 5, 2023
bc13242
Update 0198.打家劫舍.md
jianghongcheng Jun 5, 2023
3b3d9c4
Update 0213.打家劫舍II.md
jianghongcheng Jun 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions problems/0139.单词拆分.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,10 +337,53 @@ class Solution {

Python:

回溯
```python
class Solution:
def backtracking(self, s: str, wordSet: set[str], startIndex: int) -> bool:
# 边界情况:已经遍历到字符串末尾,返回True
if startIndex >= len(s):
return True

# 遍历所有可能的拆分位置
for i in range(startIndex, len(s)):
word = s[startIndex:i + 1] # 截取子串
if word in wordSet and self.backtracking(s, wordSet, i + 1):
# 如果截取的子串在字典中,并且后续部分也可以被拆分成单词,返回True
return True

# 无法进行有效拆分,返回False
return False

def wordBreak(self, s: str, wordDict: List[str]) -> bool:
wordSet = set(wordDict) # 转换为哈希集合,提高查找效率
return self.backtracking(s, wordSet, 0)

```
DP(版本一)
```python
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
wordSet = set(wordDict)
n = len(s)
dp = [False] * (n + 1) # dp[i] 表示字符串的前 i 个字符是否可以被拆分成单词
dp[0] = True # 初始状态,空字符串可以被拆分成单词

for i in range(1, n + 1): # 遍历背包
for j in range(i): # 遍历单词
if dp[j] and s[j:i] in wordSet:
dp[i] = True # 如果 s[0:j] 可以被拆分成单词,并且 s[j:i] 在单词集合中存在,则 s[0:i] 可以被拆分成单词
break

return dp[n]


```
DP(版本二)

```python
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
'''排列'''
dp = [False]*(len(s) + 1)
dp[0] = True
# 遍历背包
Expand All @@ -351,17 +394,6 @@ class Solution:
dp[j] = dp[j] or (dp[j - len(word)] and word == s[j - len(word):j])
return dp[len(s)]
```
```python
class Solution: # 和视频中写法一致(和最上面C++写法一致)
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
dp = [False]*(len(s)+1)
dp[0]=True
for j in range(1,len(s)+1):
for i in range(j):
word = s[i:j]
if word in wordDict and dp[i]: dp[j]=True
return dp[-1]
```



Expand Down
63 changes: 49 additions & 14 deletions problems/0198.打家劫舍.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,30 +166,65 @@ class Solution {
```

Python:

1维DP
```python
class Solution:
def rob(self, nums: List[int]) -> int:
if len(nums) == 0:
if len(nums) == 0: # 如果没有房屋,返回0
return 0
if len(nums) == 1:
if len(nums) == 1: # 如果只有一个房屋,返回其金额
return nums[0]

# 创建一个动态规划数组,用于存储最大金额
dp = [0] * len(nums)
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
dp[0] = nums[0] # 将dp的第一个元素设置为第一个房屋的金额
dp[1] = max(nums[0], nums[1]) # 将dp的第二个元素设置为第一二个房屋中的金额较大者

# 遍历剩余的房屋
for i in range(2, len(nums)):
dp[i] = max(dp[i-2]+nums[i], dp[i-1])
return dp[-1]
# 对于每个房屋,选择抢劫当前房屋和抢劫前一个房屋的最大金额
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])

return dp[-1] # 返回最后一个房屋中可抢劫的最大金额
```
2维DP
```python
class Solution: # 二维dp数组写法
class Solution:
def rob(self, nums: List[int]) -> int:
dp = [[0,0] for _ in range(len(nums))]
dp[0][1] = nums[0]
for i in range(1,len(nums)):
dp[i][0] = max(dp[i-1][1],dp[i-1][0])
dp[i][1] = dp[i-1][0]+nums[i]
print(dp)
return max(dp[-1])
if not nums: # 如果没有房屋,返回0
return 0

n = len(nums)
dp = [[0, 0] for _ in range(n)] # 创建二维动态规划数组,dp[i][0]表示不抢劫第i个房屋的最大金额,dp[i][1]表示抢劫第i个房屋的最大金额

dp[0][1] = nums[0] # 抢劫第一个房屋的最大金额为第一个房屋的金额

for i in range(1, n):
dp[i][0] = max(dp[i-1][0], dp[i-1][1]) # 不抢劫第i个房屋,最大金额为前一个房屋抢劫和不抢劫的最大值
dp[i][1] = dp[i-1][0] + nums[i] # 抢劫第i个房屋,最大金额为前一个房屋不抢劫的最大金额加上当前房屋的金额

return max(dp[n-1][0], dp[n-1][1]) # 返回最后一个房屋中可抢劫的最大金额

```
优化版
```python
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums: # 如果没有房屋,返回0
return 0

prev_max = 0 # 上一个房屋的最大金额
curr_max = 0 # 当前房屋的最大金额

for num in nums:
temp = curr_max # 临时变量保存当前房屋的最大金额
curr_max = max(prev_max + num, curr_max) # 更新当前房屋的最大金额
prev_max = temp # 更新上一个房屋的最大金额

return curr_max # 返回最后一个房屋中可抢劫的最大金额


```
Go:
```Go
Expand Down
103 changes: 78 additions & 25 deletions problems/0213.打家劫舍II.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,40 +130,93 @@ class Solution {
```

Python:

```Python
class Solution:
def rob(self, nums: List[int]) -> int:
#在198入门级的打家劫舍问题上分两种情况考虑
#一是不偷第一间房,二是不偷最后一间房
if len(nums)==1:#题目中提示nums.length>=1,所以不需要考虑len(nums)==0的情况
if len(nums) == 0:
return 0
if len(nums) == 1:
return nums[0]
val1=self.roblist(nums[1:])#不偷第一间房
val2=self.roblist(nums[:-1])#不偷最后一间房
return max(val1,val2)

def roblist(self,nums):
l=len(nums)
dp=[0]*l
dp[0]=nums[0]
for i in range(1,l):
if i==1:
dp[i]=max(dp[i-1],nums[i])
else:
dp[i]=max(dp[i-1],dp[i-2]+nums[i])
return dp[-1]

result1 = self.robRange(nums, 0, len(nums) - 2) # 情况二
result2 = self.robRange(nums, 1, len(nums) - 1) # 情况三
return max(result1, result2)
# 198.打家劫舍的逻辑
def robRange(self, nums: List[int], start: int, end: int) -> int:
if end == start:
return nums[start]

prev_max = nums[start]
curr_max = max(nums[start], nums[start + 1])

for i in range(start + 2, end + 1):
temp = curr_max
curr_max = max(prev_max + nums[i], curr_max)
prev_max = temp

return curr_max

```
2维DP
```python
class Solution: # 二维dp数组写法
class Solution:
def rob(self, nums: List[int]) -> int:
if len(nums)<3: return max(nums)
return max(self.default(nums[:-1]),self.default(nums[1:]))
def default(self,nums):
dp = [[0,0] for _ in range(len(nums))]
if len(nums) < 3:
return max(nums)

# 情况二:不抢劫第一个房屋
result1 = self.robRange(nums[:-1])

# 情况三:不抢劫最后一个房屋
result2 = self.robRange(nums[1:])

return max(result1, result2)

def robRange(self, nums):
dp = [[0, 0] for _ in range(len(nums))]
dp[0][1] = nums[0]
for i in range(1,len(nums)):
dp[i][0] = max(dp[i-1])
dp[i][1] = dp[i-1][0] + nums[i]

for i in range(1, len(nums)):
dp[i][0] = max(dp[i - 1])
dp[i][1] = dp[i - 1][0] + nums[i]

return max(dp[-1])



```

优化版
```python
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums: # 如果没有房屋,返回0
return 0

if len(nums) == 1: # 如果只有一个房屋,返回该房屋的金额
return nums[0]

# 情况二:不抢劫第一个房屋
prev_max = 0 # 上一个房屋的最大金额
curr_max = 0 # 当前房屋的最大金额
for num in nums[1:]:
temp = curr_max # 临时变量保存当前房屋的最大金额
curr_max = max(prev_max + num, curr_max) # 更新当前房屋的最大金额
prev_max = temp # 更新上一个房屋的最大金额
result1 = curr_max

# 情况三:不抢劫最后一个房屋
prev_max = 0 # 上一个房屋的最大金额
curr_max = 0 # 当前房屋的最大金额
for num in nums[:-1]:
temp = curr_max # 临时变量保存当前房屋的最大金额
curr_max = max(prev_max + num, curr_max) # 更新当前房屋的最大金额
prev_max = temp # 更新上一个房屋的最大金额
result2 = curr_max

return max(result1, result2)


```
Go:
Expand Down
67 changes: 46 additions & 21 deletions problems/0279.完全平方数.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,36 +217,61 @@ class Solution {

Python:

先遍历物品, 再遍历背包
```python
class Solution:
def numSquares(self, n: int) -> int:
'''版本一,先遍历背包, 再遍历物品'''
# 初始化
nums = [i**2 for i in range(1, n + 1) if i**2 <= n]
dp = [10**4]*(n + 1)
dp = [float('inf')] * (n + 1)
dp[0] = 0
# 遍历背包
for j in range(1, n + 1):
# 遍历物品
for num in nums:
if j >= num:
dp[j] = min(dp[j], dp[j - num] + 1)

for i in range(1, n + 1): # 遍历背包
for j in range(1, int(i ** 0.5) + 1): # 遍历物品
# 更新凑成数字 i 所需的最少完全平方数数量
dp[i] = min(dp[i], dp[i - j * j] + 1)

return dp[n]

def numSquares1(self, n: int) -> int:
'''版本二, 先遍历物品, 再遍历背包'''
# 初始化
nums = [i**2 for i in range(1, n + 1) if i**2 <= n]
dp = [10**4]*(n + 1)

```
先遍历背包, 再遍历物品
```python
class Solution:
def numSquares(self, n: int) -> int:
dp = [float('inf')] * (n + 1)
dp[0] = 0
# 遍历物品
for num in nums:
# 遍历背包
for j in range(num, n + 1):
dp[j] = min(dp[j], dp[j - num] + 1)

for i in range(1, int(n ** 0.5) + 1): # 遍历物品
for j in range(i * i, n + 1): # 遍历背包
# 更新凑成数字 j 所需的最少完全平方数数量
dp[j] = min(dp[j - i * i] + 1, dp[j])

return dp[n]


```
其他版本
```python
class Solution:
def numSquares(self, n: int) -> int:
# 创建动态规划数组,初始值为最大值
dp = [float('inf')] * (n + 1)
# 初始化已知情况
dp[0] = 0

# 遍历背包容量
for i in range(1, n + 1):
# 遍历完全平方数作为物品
j = 1
while j * j <= i:
# 更新最少完全平方数的数量
dp[i] = min(dp[i], dp[i - j * j] + 1)
j += 1

# 返回结果
return dp[n]



```
Go:
```go
// 版本一,先遍历物品, 再遍历背包
Expand Down
Loading