diff --git a/@_M%)AU31060_V$0LDVY]F9.png b/@_M%)AU31060_V$0LDVY]F9.png deleted file mode 100644 index 842e5a32351566e0fd41b541c3d7865b987e10fb..0000000000000000000000000000000000000000 Binary files a/@_M%)AU31060_V$0LDVY]F9.png and /dev/null differ diff --git a/K1[@K`S1RNQW~[1_5{$6Q98.png b/K1[@K`S1RNQW~[1_5{$6Q98.png deleted file mode 100644 index af894c0de7b265ab5d5de12945d3a828305937a4..0000000000000000000000000000000000000000 Binary files a/K1[@K`S1RNQW~[1_5{$6Q98.png and /dev/null differ diff --git a/Subset.cpp b/Subset.cpp deleted file mode 100644 index 1ed1c0ed0afdba4fb7cd7f97151bda09463535b9..0000000000000000000000000000000000000000 --- a/Subset.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -using namespace std; -vector> subsets(vector& nums) -{ - vector t; - vector> ans; - int n = nums.size(); - for (int mask = 0; mask < (1 << n); ++mask) { - t.clear(); - for (int i = 0; i < n; ++i) { - if (mask & (1 << i)) { - t.push_back(nums[i]); - } - } - ans.push_back(t); - } - return ans; -} -int main() -{ - vector nums = {1,2,3}; - subsets(nums); -} \ No newline at end of file diff --git a/U$T4H13}PTOP8S}}@P~V`QK.png b/U$T4H13}PTOP8S}}@P~V`QK.png deleted file mode 100644 index 06096a6039daee5e11efadba1d20afb587a2f3b5..0000000000000000000000000000000000000000 Binary files a/U$T4H13}PTOP8S}}@P~V`QK.png and /dev/null differ diff --git a/WordBreak.py b/WordBreak.py deleted file mode 100644 index 93babe1354e2883e0f00048bf33926a094ab8b50..0000000000000000000000000000000000000000 --- a/WordBreak.py +++ /dev/null @@ -1,16 +0,0 @@ - -def wordBreak( s: str, wordDict: list[str]) -> bool: - n=len(s) - dp=[False]*(n+1) - dp[0]=True - for i in range(n): - for j in range(i+1,n+1): - if(dp[i] and (s[i:j] in wordDict)): - dp[j]=True - print(dp[-1]) - return dp[-1] - - -s="applephone" -wordDict=['apple','phone'] -wordBreak( s, wordDict) diff --git a/alg.md b/alg.md new file mode 100644 index 0000000000000000000000000000000000000000..271e21d2fd04625453e368924186838dfafd6463 --- /dev/null +++ b/alg.md @@ -0,0 +1,154 @@ +# 解题报告 + +## 1.插入后的最大值 + +### 题目描述 + +给你一个非常大的整数 `n` 和一个整数数字 `x` ,大整数 `n` 用一个字符串表示。`n` 中每一位数字和数字`x` 都处于闭区间` [1, 9]` 中,且 `n` 可能表示一个 负数 。 + +你打算通过在`n`的十进制表示的任意位置插入`x`来**最大化** `n` 的 **数值** 。但 **不能** 在负号的左边插入` x` 。 + +- 例如,如果 `n = 73` 且 `x = 6` ,那么最佳方案是将 `6` 插入 `7` 和 `3` 之间,使 `n = 763` 。 +- 如果 `n = -55` 且 `x = 2` ,那么最佳方案是将 `2` 插在第一个 `5` 之前,使 `n = -255` 。 + +返回插入操作后,用字符串表示的 `n` 的最大值。 + +### 思路分析 + +由于插入操作不会改变 `n` 的符号,因此如果 `n` 为负数,那么插入后的最大值对应的**绝对值**最小;如果`n`为正数,那么插入后的最大值对应的**绝对值**最大。我们首先通过 *n* 的第一个字符是否为 ‘-‘ 确定它为负数还是正数,进而判断我们需要找到的绝对值应当最大还是最小。 + +1. 如果 `n` 是负数,那么若 `n` 中存在比 `x` 小的位,那么这些位之前的插入位置中的第一个对应的插入后绝对值一定是最大的;若`n`中存在比 x 大的位,那么这些位之前的插入位置中的第一个对应的插入后绝对值一定是最小的。我们需要寻找 `n` 中第一个比`x` 大的位置。如果存在,则返回对应的插入后字符串;如果不存在,则返回 `x` 插入 `n` 结尾对应的字符串。 +2. 如果 `n` 是正数,类似地,我们需要寻找 `n` 中第一个比 `x` 小的位置。如果存在,则返回对应的插入后字符串;如果不存在,则返回 `x` 插入 `n` 结尾对应的字符串。 +### 代码实现 + +```python +class Solution: + def maxValue(self, n: str, x: int) -> str: + l = len(n) + if n[0] == '-': + for i in range(1, l): + if int(n[i]) > x: + return n[:i] + str(x) + n[i:] + return n + str(x) + else: + for i in range(l): + if int(n[i]) < x: + return n[:i] + str(x) + n[i:] + return n + str(x) +``` + +### 复杂度分析 + +- 时间复杂度:***O(l)***,其中 `l` 为 `n` 的长度。遍历 `n` 寻找插入位置的最坏时间复杂度为 ***O(l)***,将数字插入字符串的最坏时间复杂度为 ***O(l)***。 +- 空间复杂度:***O(1)***。 + +## 2.全排列 + +### 题目描述 + +给定一个不含重复数字的数组 `nums` ,返回其 *所有可能的全排列* 。你可以 **按任意顺序** 返回答案。 + +### 思路分析 + +这个问题可以看作有 `n` 个排列成一行的空格,我们需要从左往右依此填入题目给定的 `n` 个数,每个数只能使用一次。那么很直接的可以想到一种穷举的算法,即从左往右每一个位置都依此尝试填入一个数,看能不能填完这 `n` 个空格,在程序中我们可以用「回溯法」来模拟这个过程。 + +我们定义递归函数 `backtrack(first,output)` 表示从左往右填到第 `first` 个位置,当前排列为`output`。 那么整个递归函数分为两个情况: + +- 如果 `first=n`,说明我们已经填完了 `n` 个位置(注意下标从 0 开始),找到了一个可行的解,我们将 `output` 放入答案数组中,递归结束。 +- 如果 `first int: + size = len(nums) + if size == 0: + return 0 + return self.__max_sub_array(nums, 0, size - 1) + + def __max_sub_array(self, nums, left, right): + if left == right: + return nums[left] + mid = (left + right) >> 1 + return max(self.__max_sub_array(nums, left, mid), + self.__max_sub_array(nums, mid + 1, right), + self.__max_cross_array(nums, left, mid, right)) + + def __max_cross_array(self, nums, left, mid, right): + # 一定包含 nums[mid] 元素的最大连续子数组的和, + # 思路是看看左边"扩散到底",得到一个最大数,右边"扩散到底"得到一个最大数 + # 然后再加上中间数 + left_sum_max = 0 + start_left = mid - 1 + s1 = 0 + while start_left >= left: + s1 += nums[start_left] + left_sum_max = max(left_sum_max, s1) + start_left -= 1 + + right_sum_max = 0 + start_right = mid + 1 + s2 = 0 + while start_right <= right: + s2 += nums[start_right] + right_sum_max = max(right_sum_max, s2) + start_right += 1 + return left_sum_max + nums[mid] + right_sum_max +``` + +### 复杂度分析 + +- 时间复杂度:***O(NlogN)***,这里递归的深度是对数级别的,每一层需要遍历一遍数组(或者数组的一半、四分之一); +- 空间复杂度:***O(logN)***,需要常数个变量用于选取最大值,需要使用的空间取决于递归栈的深度。 + + diff --git a/alg1.md b/alg1.md deleted file mode 100644 index 90fd1f1c7e2247dd65d21750025c8a9862cefccc..0000000000000000000000000000000000000000 --- a/alg1.md +++ /dev/null @@ -1,59 +0,0 @@ -# 算法设计第四次作业 - -### 根据身高重建队列 - -1.问题描述 -给定一个数组 `people`,其中 `people[i]` 表示第 `i` 个人的身高为 `people[i][0]`,前面正好有 `people[i][1]` 个身高大于或等于 `people[i][0]` 的人。 -请你按照身高从高到低重新排列 `people` 数组,使得每个人重新排列后的位置与其原来的位置相同,并且前面只有比他高的人或和他身高相同的人。 - -2.*思路*:首先对数对进行排序,按照数对的元素 1 降序排序,按照数对的元素 2 升序排序。原因是,按照元素 1 进行降序排序,对于每个元素,在其之前的元素的个数,就是大于等于他的元素的数量,而按照第二个元素正向排序,我们希望 k 大的尽量在后面,减少插入操作的次数。 - -```python -class Solution: - def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]: - res = [] - people = sorted(people, key = lambda x: (-x[0], x[1])) - for p in people: - if len(res) <= p[1]: - res.append(p) - elif len(res) > p[1]: - res.insert(p[1], p) - return res -``` - - - -###### 3.性能分析 - - - -**空间性能**: -$$ -O(n) -$$ -因为代码中需要使用一个列表来存储插入之后的队列,而队列的长度为 n,所以空间复杂度为 O(n)。 - -**时间性能**: -$$ -O(n^2) -$$ - -其中 n是数组 `people` 的长度。因为代码中使用了一个循环遍历所有的人,并根据每个人的k值将其插入到对应的位置上。由于需要不断地插入元素,导致时间复杂度为 O(n^2) - -###### 4.代码测试 - -![](C:\Users\崔\Pictures\Screenshots\屏幕截图 2023-05-19 142401.png) - -###### 5.心得体会 - -git使用愈发熟悉,在文件的创建和对文件的提交上掌握程度提高,不会的问题及时询问同学解决。 - -###### 6.实验环境 - -win11. - -python3.11 - -vs2022 - -git. diff --git a/alg1.py b/alg1.py index 8674a6e0596ac27f4819bfa439f93fdebc03fe1a..726c54d385677e901f17574d263e9b72835b51cc 100644 --- a/alg1.py +++ b/alg1.py @@ -1,10 +1,12 @@ -class Solution: - def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]: - res = [] - people = sorted(people, key = lambda x: (-x[0], x[1])) - for p in people: - if len(res) <= p[1]: - res.append(p) - elif len(res) > p[1]: - res.insert(p[1], p) - return res \ No newline at end of file +def maxValue(n: str, x: int): + l = len(n) + if n[0] == '-': + for i in range(1, l): + if int(n[i]) > x: + return n[:i] + str(x) + n[i:] + return n + str(x) + else: + for i in range(l): + if int(n[i]) < x: + return n[:i] + str(x) + n[i:] + return n + str(x) \ No newline at end of file diff --git a/alg2.md b/alg2.md deleted file mode 100644 index a4d3b2bb38e2daa0d5fa4bbb3cce64fc44a67cc7..0000000000000000000000000000000000000000 --- a/alg2.md +++ /dev/null @@ -1,81 +0,0 @@ -# 算法设计第四次作业 - -### 分割回文串 - -1.问题描述给你一个字符串 `s`,请你将 `s` 分割成一些子串,使每个子串都是 **回文串** 。返回 `s` 所有可能的分割方案。 - -**回文串** 是正着读和反着读都一样的字符串。 - -2.*思路*: - -确定状态:定义状态 dp[i] 表示字符串 s中前 i 个字符可以被分割成的最小回文串数量。 - -转移方程:对于一个回文串 s[j:i],若 s[j:i] 是回文串,则可以将其作为一个独立的回文串,此时状态转移方程为 - -dp[i] = min(dp[i], dp[j-1]+1),其中 dp[j-1]+1 表示将 s[j:i] 作为一个独立的回文串,所需的最小回文串数量。 - -初始状态:dp[0]=0,即空字符串的最小回文串数量为 0。 - 计算顺序:由于转移方程需要用到 dp[j-1],因此需要先计算出 dp[0], dp[1], ..., dp[j-1] 的值,再计算 dp[j], dp[j+1], ..., dp[n] 的值。 - 最终结果:最终答案为 dp[n],其中 n 为字符串 s 的长度。 - -```python -class Solution: - def partition(self, s: str) -> List[List[str]]: - res = [] - n = len(s) - # dp[i][j] 表示 s[i:j+1] 是否为回文串 - dp = [[False] * n for _ in range(n)] - for i in range(n): - dp[i][i] = True - for j in range(i): - if s[i] == s[j] and (i - j <= 2 or dp[j+1][i-1]): - dp[j][i] = True - path = [] - def dfs(start): - if start == n: - res.append(path[:]) - return - for i in range(start, n): - if dp[start][i]: - path.append(s[start:i+1]) - dfs(i+1) - path.pop() - dfs(0) - return res - -``` - - - -###### 3.性能分析 - - - -**空间性能**: -$$ -O(n^2) -$$ -其中 n 是字符串 `s` 的长度。需要 $O(n^2)$ 的空间存储 `dp` 数组,以及 O(n) 的栈空间用于 `dfs` 函数的递归调用。因此总空间复杂度为 O(n^2)。 - -**时间性能**: -$$ -O(n^2+2^n) -$$ - -其中 n 是字符串 `s` 的长度。需要 O(n^2) 的时间计算 `dp` 数组,然后需要 O(2^n) 的时间枚举所有的分割方案。因此总时间复杂度为 O(n^2+2^n)。 - -###### 4.代码测试 - -![](C:\Users\崔\Pictures\Screenshots\屏幕截图 2023-05-19 144107.png) - - - -###### 5.实验环境 - -win11. - -python3.11 - -vs2022 - -git. diff --git a/alg2.py b/alg2.py index 433a3c1a5c710d3eaacdf1758ef6466451c68cfc..8db3ebd05bace8312b5b5687f81cd12ace7c8445 100644 --- a/alg2.py +++ b/alg2.py @@ -1,23 +1,21 @@ -class Solution: - def partition(self, s: str) -> List[List[str]]: - res = [] - n = len(s) - # dp[i][j] 表示 s[i:j+1] 是否为回文串 - dp = [[False] * n for _ in range(n)] - for i in range(n): - dp[i][i] = True - for j in range(i): - if s[i] == s[j] and (i - j <= 2 or dp[j+1][i-1]): - dp[j][i] = True - path = [] - def dfs(start): - if start == n: - res.append(path[:]) - return - for i in range(start, n): - if dp[start][i]: - path.append(s[start:i+1]) - dfs(i+1) - path.pop() - dfs(0) - return res +def permute(nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + def backtrack(first = 0): + # 所有数都填完了 + if first == n: + res.append(nums[:]) + for i in range(first, n): + # 动态维护数组 + nums[first], nums[i] = nums[i], nums[first] + # 继续递归填下一个数 + backtrack(first + 1) + # 撤销操作 + nums[first], nums[i] = nums[i], nums[first] + + n = len(nums) + res = [] + backtrack() + return res \ No newline at end of file diff --git a/alg3.md b/alg3.md deleted file mode 100644 index 020b0bbaa5aea1cf12a49af79313e0363a9a8759..0000000000000000000000000000000000000000 --- a/alg3.md +++ /dev/null @@ -1,58 +0,0 @@ -# 算法设计第四次作业 - -### 不同路径 - -1.问题描述 -一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 - -机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 - -问总共有多少条不同的路径? - -2.*思路*: - -确定状态:定义状态 dp[i][j]表示从起点到达坐标为 $(i,j)$ 的格子的不同路径数量。 -转移方程:由于只能向下或向右走,因此到达格子 $(i,j)$ 的路径数量为到达格子 (i-1,j) 和 (i,j-1) 的路径数量之和,即 dp[i][j] = dp[i-1][j] + dp[i][j-1]。 -初始状态:第一行和第一列的格子只能向右或向下走,因此到达这些格子的路径数量都为 1,即 dp[0][j] = dp[i][0] = 1。 计算顺序:由于转移方程需要用到 dp[i-1][j] 和 dp[i][j-1],因此需要从第二行和第二列开始计算,依次计算 dp[2][2], dp[2][3], ..., dp[2][n], dp[3][2], dp[3][3], ..., dp[m][n]的值。 -最终结果:最终答案为 dp[m][n],其中 m 和 n 分别为网格的行数和列数。 - -```python -class Solution: - def uniquePaths(self, m: int, n: int) -> int: - dp = [[1] * n for _ in range(m)] # 初始化为 1 - for i in range(1, m): - for j in range(1, n): - dp[i][j] = dp[i-1][j] + dp[i][j-1] - return dp[m-1][n-1] -``` - - - -###### 3.性能分析 - - - -**空间性能**: -$$ -O(n) -$$ -**时间性能**: -$$ -O(mn) -$$ - -###### 4.代码测试 - -![](C:\Users\崔\Pictures\Screenshots\屏幕截图 2023-05-19 145711.png) - - - -###### 5.实验环境 - -win11. - -python3.11 - -vs2022 - -git. diff --git a/alg3.py b/alg3.py index 9ab3fd64a630ddf559d1f426f53539c6cadb1b8a..5b7b6ddaaf20bffa6b5728ac0f057a2598e7bc7f 100644 --- a/alg3.py +++ b/alg3.py @@ -1,7 +1,34 @@ -class Solution: - def uniquePaths(self, m: int, n: int) -> int: - dp = [[1] * n for _ in range(m)] # 初始化为 1 - for i in range(1, m): - for j in range(1, n): - dp[i][j] = dp[i-1][j] + dp[i][j-1] - return dp[m-1][n-1] \ No newline at end of file +def maxSubArray(nums): + size = len(nums) + if size == 0: + return 0 + return __max_sub_array(nums, 0, size - 1) + +def __max_sub_array(nums, left, right): + if left == right: + return nums[left] + mid = (left + right) >> 1 + return max(__max_sub_array(nums, left, mid), + __max_sub_array(nums, mid + 1, right), + __max_cross_array(nums, left, mid, right)) + +def __max_cross_array(nums, left, mid, right): + # 一定包含 nums[mid] 元素的最大连续子数组的和, + # 思路是看看左边"扩散到底",得到一个最大数,右边"扩散到底"得到一个最大数 + # 然后再加上中间数 + left_sum_max = 0 + start_left = mid - 1 + s1 = 0 + while start_left >= left: + s1 += nums[start_left] + left_sum_max = max(left_sum_max, s1) + start_left -= 1 + + right_sum_max = 0 + start_right = mid + 1 + s2 = 0 + while start_right <= right: + s2 += nums[start_right] + right_sum_max = max(right_sum_max, s2) + start_right += 1 + return left_sum_max + nums[mid] + right_sum_max \ No newline at end of file diff --git a/gen1.py b/gen1.py index d4ca40fe71779c6626ace5181d545035ef8e6eca..fe97e8b7a8dc8126a072a0a67e79ea7c86117eed 100644 --- a/gen1.py +++ b/gen1.py @@ -1,10 +1,2 @@ -import random -n = 10 # 数组长度 -max_height = 200 # 最大身高 -max_k = n # 最大k值 -people = [] -for i in range(n): - height = random.randint(1, max_height) - k = random.randint(0, max_k) - people.append([height, k]) -print(people) \ No newline at end of file +n = "123" +x = 6 \ No newline at end of file diff --git a/gen2.py b/gen2.py index 1cae8ae5e4667c9c5167bea36d3aa2137aaf239a..2fb3f8c70410a4664128dc1063593c7f106a5224 100644 --- a/gen2.py +++ b/gen2.py @@ -1,8 +1 @@ -import random -import string -def generate_data(n): - s = ''.join(random.choice(string.ascii_lowercase) for _ in range(n)) - return s -n = 10 -s = generate_data(n) -print(s) \ No newline at end of file +nums = [1, 2, 3] \ No newline at end of file diff --git a/gen3.py b/gen3.py index a6087188894922a918c9ac470282689ffd7c4add..9033ff8dfeae798806e4da1fa37a9f314b537770 100644 --- a/gen3.py +++ b/gen3.py @@ -1,13 +1 @@ -import random -def generate_data(): - m, n = random.randint(1, 10), random.randint(1, 10) - return m, n -def run_test(m, n): - dp = [[1] * n for _ in range(m)] - for i in range(1, m): - for j in range(1, n): - dp[i][j] = dp[i-1][j] + dp[i][j-1] - return dp[m-1][n-1] -m, n = generate_data() -print("m={}, n={}".format(m, n)) -print("Result:", run_test(m, n)) \ No newline at end of file +nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4] \ No newline at end of file diff --git a/integerReplacement.cpp b/integerReplacement.cpp deleted file mode 100644 index d91ca49718b2887d66f1444bf9bcb94f26027ec0..0000000000000000000000000000000000000000 --- a/integerReplacement.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -using namespace std; -int main() -{ - int n; cin >> n; - int ans = 0; - while (n != 1) { - if (n % 2 == 0) - { - n = n / 2; - } - else if (n == 3) - { - n = 2; - } - else - { - n = n + 1; - } - ans++; - } - cout << ans; - return 0; -} \ No newline at end of file diff --git a/test1.py b/test1.py index 0d51413738859b97d9ca99d5eded5e85bcf356fd..90eca9d6d68b8e5593140797342d2930006f6d6b 100644 --- a/test1.py +++ b/test1.py @@ -1,10 +1,7 @@ -import random -n = 10 # 数组长度 -max_height = 200 # 最大身高 -max_k = n # 最大k值 -people = [] -for i in range(n): - height = random.randint(1, max_height) - k = random.randint(0, max_k) - people.append([height, k]) -print(people) +import gen1 +import alg1 +n = gen1.n +x = gen1.x +print(n, x) +a = alg1.maxValue(n, x) +print(a) \ No newline at end of file diff --git a/test2.py b/test2.py index e5fc19dc8a135e3164f3ea950873222bb6858837..9c532ef7b00fae78fcf62a235445c0a1f75763e4 100644 --- a/test2.py +++ b/test2.py @@ -1 +1,7 @@ -tqjpusyvcm \ No newline at end of file +import gen2 +import alg2 + +n = gen2.nums +print(n) +a = alg2.permute(n) +print(a) \ No newline at end of file diff --git a/test3.py b/test3.py index fc9cf99e65e7cdc968747a93a19e69e9add7ec41..952040626b6492de598bf397983aed6372c95896 100644 --- a/test3.py +++ b/test3.py @@ -1,2 +1,7 @@ -m=5, n=4 -Result: 35 +import gen3 +import alg3 + +n = gen3.nums +print(n) +a = alg3.maxSubArray(n) +print(a) \ No newline at end of file diff --git "a/\345\261\217\345\271\225\346\210\252\345\233\276 2023-05-21 173336.png" "b/\345\261\217\345\271\225\346\210\252\345\233\276 2023-05-21 173336.png" new file mode 100644 index 0000000000000000000000000000000000000000..4b444153e686d4ee00ca89f518cf7f958726fd6f Binary files /dev/null and "b/\345\261\217\345\271\225\346\210\252\345\233\276 2023-05-21 173336.png" differ diff --git "a/\347\256\227\346\263\225\350\256\276\350\256\241\345\210\206\346\236\220s=\345\256\236\351\252\214\345\233\233.md" "b/\347\256\227\346\263\225\350\256\276\350\256\241\345\210\206\346\236\220s=\345\256\236\351\252\214\345\233\233.md" deleted file mode 100644 index 1f532e9f16f524cb6d36b4a80dad032e3d1aa643..0000000000000000000000000000000000000000 --- "a/\347\256\227\346\263\225\350\256\276\350\256\241\345\210\206\346\236\220s=\345\256\236\351\252\214\345\233\233.md" +++ /dev/null @@ -1,191 +0,0 @@ -# 算法设计分析 - -### 单词拆分 - -###### 1.算法实现及测试 - -```python -def wordBreak( s: str, wordDict: list[str]) -> bool: - n=len(s) - dp=[False]*(n+1) - dp[0]=True - for i in range(n): - for j in range(i+1,n+1): - if(dp[i] and (s[i:j] in wordDict)): - dp[j]=True - print(dp[-1]) - return dp[-1] - - -s="applephone" -wordDict=['apple','phone'] -wordBreak( s, wordDict) -``` - -*思路*: - -1.把单词拆分成每一个字母, - -| | a | p | p | l | e | p | h | o | n | e | -| ---- | :---: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | ---- | :--: | -| true | false | f | f | f | t | f | f | f | f | t | - -2.初始化dp=[f,f,........,f]长度为n+1.n为字符串长度。dp[i]表示s的前i位是否可以用字典中的单词表示。 - -3.初始化dp[0]=true,空字符可以表示。 - -4.遍历字符串的所有子串,遍历开始索引i,遍历区间(0,n).遍历结束索引j,遍历区间(i+,n+1). - - - -**动态规划**:动态规划(英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。 - -###### 3.性能分析 - -**时间复杂度**: -$$ -O(n^2) -$$ -**空间复杂度**: -$$ -O(n) -$$ - - - -### 整数转换 - -###### 1.算法实现及测试 - -```c++ -#include -using namespace std; -int main() -{ - int n; cin >> n; - int ans = 0; - while (n != 1) { - if (n % 2 == 0) - { - n = n / 2; - } - else if (n == 3) - { - n = 2; - } - else - { - n = n + 1; - } - ans++; - } - cout << ans; - return 0; -} -``` - -*思路*: - -不断的转换,将偶数转换成其1/2,奇数先加一或减一再转换成其1/2,考虑特殊情况3,此时加一,变成四,减一变成二,所以到三时减一更优。 - -**贪心算法**:贪心算法(greedy algorithm ,又称贪婪算法)是指,在对[问题求解](https://baike.baidu.com/item/问题求解/6693186?fromModule=lemma_inlink)时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,[算法](https://baike.baidu.com/item/算法/209025?fromModule=lemma_inlink)得到的是在某种意义上的局部最优解 。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择 - -###### 3.性能分析 - -**时间复杂度**: -$$ -O(n) -$$ -**空间复杂度**: -$$ -O(n) -$$ - - - -### 求所有子集 - -###### 1.算法实现及测试 - -```c++ -#include -#include -using namespace std; -vector> subsets(vector& nums) -{ - vector t; - vector> ans; - int n = nums.size(); - for (int mask = 0; mask < (1 << n); ++mask) { - t.clear(); - for (int i = 0; i < n; ++i) { - if (mask & (1 << i)) { - t.push_back(nums[i]); - } - } - ans.push_back(t); - } - return ans; -} -int main() -{ - vector nums = {1,2,3}; - subsets(nums); -} -``` - -*思路*: - -记原序列中元素总数为n,原序列每个数字ai的状态有两种,在或不在子集中。我们用1表示在,0表示不在,那么每一个子集对应一个长度为n的0/1序列。如{1,2,3}. - -| 0/1序列 | 子集 | 二进制数 | -| ------- | --------- | -------- | -| 000 | {} | 0 | -| 001 | {3} | 1 | -| 010 | {2} | 2 | -| 011 | {2,3} | 3 | -| 100 | {1} | 4 | -| 101 | {1,3} | 5 | -| 110 | {1,2} | 6 | -| 111 | {1,2,3} | 7 | - -发现0/1序列对应的二进制数正好从0到2的n次方减一。枚举mask。其而记者表示是一个0/1序列。按照0/1序列从原集中取数。 - -**贪心算法**:回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优[搜索](https://baike.baidu.com/item/搜索/2791632?fromModule=lemma_inlink)法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。 - -###### 3.性能分析 - -**时间复杂度**: -$$ -O(n*2^n) -$$ -**空间复杂度**: -$$ -O(n) -$$ - - - - - -**代码测试** - -![](C:\Users\20292\Desktop\@_M%)AU31060_V$0LDVY]F9.png) - -![](C:\Users\20292\Desktop\K1[@K`S1RNQW~[1_5{Q98.png) - -![](C:\Users\20292\Desktop\U$T4H13}PTOP8S}}@P~V`QK.png) - -5.心得体会 - -这是最后一次实验,代码部分分别用了python和c++,因为对他们的掌握程度不同,比较熟悉的用了c++,写起来相对容易的用了python。对于git的使用,基本的提交,合并等操作已经没有什么问题了。markdown语法也比较熟练。最主要的问题还是在算法的理解和代码的编写上,有的部分仍然不太清楚,有参考网上的代码。自我感觉还是应该多上手写。 - -###### 6.实验环境 - -win11. - -python3.11 - -vs2022 - -git. \ No newline at end of file