【刷题日记】动态规划经典题目

article/2025/10/7 4:48:33

😀大家好,我是白晨,一个不是很能熬夜😫,但是也想日更的人✈。如果喜欢这篇文章,点个赞👍,关注一下👀白晨吧!你的支持就是我最大的动力!💪💪💪

在这里插入图片描述

文章目录

  • 🍇前言
  • 🥝动态规划经典题目
    • 🍕1.斐波那契数列
    • 🍔2.拆分词句
    • 🍟3.三角矩阵
    • 🌭4.求路径
    • 🍿5.带权值的最小路径和
    • 🧂6.背包问题
    • 🥓7.分割回文串
    • 🥚8.编辑距离
    • 🍳9.不同子序列
  • 🍉总结

🍇前言


观前提醒:这篇文章需要一定动态规划的基础😜

🎈动态规划的方法大多数都非常的抽象,而且在生活中适用的范围也很广。这个算法的抽象性就要求学习动态规划算法时,不能只看算法的思路,而不去做题。

所以,白晨整理了动态规划中非常经典的题目以供大家更好掌握动态规划算法,题目范围从矩阵到字符串等,难度从易到难,抽象程度从一维到二维

如果你没有接触过动态规划思想 或者 其中有些题目实在想不懂 也没有关系🍈,白晨将在不久后发布动态规划算法的全解析,并在其中在再次着重讲述动态规划中比较难的题目,如背包问题等。


🥝动态规划经典题目

🍕1.斐波那契数列


在这里插入图片描述

原题链接:斐波那契数列

这道题可能是一道大家刚学C语言的时候就做过的一道题,我们现在按照动态规划的思想来分析一下这道题:

  1. 这道题的状态是什么?

    也就是我们需要解决/面对什么,这里我们需要解决的是斐波那契数列第n项的数值,所以我们设第n项数值为 f ( n ) f(n) f(n) ,也即状态为 f ( n ) f(n) f(n)

  2. 状态转移方程是什么?

    这里我们可以分析状态,采用 我要从哪里来 的思路,可以轻松得到 f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n - 1) + f(n - 2) f(n)=f(n1)+f(n2)

  3. 状态的初始化是什么?

    也就是一开始的状态是什么?

    f ( 1 ) = 1 , f ( 2 ) = 1 f(1) = 1 , f(2) = 1 f(1)=1,f(2)=1

  4. 返回值

    由上面就可以得到返回值就为 f ( n ) f(n) f(n)

总结一下:

  • 状态: f ( k ) f(k) f(k)
  • 状态递推: f ( k ) = f ( k − 1 ) + f ( k − 2 ) f(k) = f(k - 1) + f(k - 2) f(k)=f(k1)+f(k2)
  • 初始值: f ( 1 ) = f ( 2 ) = 1 f(1) = f(2) = 1 f(1)=f(2)=1
  • 返回结果: f ( n ) f(n) f(n)

根据上述分析得到具体代码:

class Solution {
public:int Fibonacci(int n) {int fib1 = 1;int fib2 = 1;int f;if (n == 1 || n == 2)return 1;for (int i = 3; i <= n; i++){f = fib1 + fib2;fib2 = fib1;fib1 = f;}return f;}
};

🍔2.拆分词句


在这里插入图片描述

原题链接:拆分词句

状态
子状态:前1,2,3,…,n个字符能否根据词典中的词被成功分词

  • F ( i ) F(i) F(i) : 前 i 个字符能否根据词典中的词被成功分词

状态递推

  • F ( i ) F(i) F(i): true{$j < i $ && F ( j ) F(j) F(j) && s u b s t r [ j + 1 , i ] substr[j+1,i] substr[j+1,i] 能在词典中找到} OR false
  • j小于i中,只要能找到一个 F ( j ) F(j) F(j)为true,并且从 j+1i 之间的字符能在词典中找到,则 F ( i ) F(i) F(i) 为true

初始值

  • 对于初始值无法确定的,可以引入一个不代表实际意义的空状态,作为状态的起始;
  • 空状态的值需要保证状态递推可以正确且顺利的进行,到底取什么值可以通过简单的例子进行验证
  • F ( 0 ) = t r u e F(0) = true F(0)=true

返回结果 F ( n ) F(n) F(n)

class Solution {
public:bool wordBreak(string s, unordered_set<string>& dict) {if (s.empty())return false;if (dict.empty())return false;vector<bool> can_spe(s.size() + 1, false);// 初始化can_spe[0] = true;for (int i = 1; i <= s.size(); i++){for (int j = i - 1; j >= 0; j--){// 当前 j 个字符能从字典中分割,并且 [j + 1, i] 的字符正好为字典中的字符时// 判断为真if (can_spe[j] && dict.find(s.substr(j, i - j)) != dict.end()){can_spe[i] = true;break;}}}return can_spe[s.size()];}
};

🍟3.三角矩阵


在这里插入图片描述

原题链接:三角形

在这里插入图片描述

class Solution {
public:int minimumTotal(vector<vector<int> >& triangle) {if (triangle.empty())return 0;int row = triangle.size();for (int i = 1; i < row; i++){for (int j = 0; j <= i; j++){// 初始化if (j == 0)triangle[i][0] = triangle[i - 1][0] + triangle[i][0];else if (j == i)triangle[i][j] = triangle[i - 1][j - 1] + triangle[i][j];// 选出到达 [i][j] 的最小值elsetriangle[i][j] = min(triangle[i - 1][j], triangle[i - 1][j - 1]) + triangle[i][j];}}int Min = triangle[row - 1][0];// 遍历最后一行,选出最小值for (int j = 1; j < row; j++)Min = min(Min, triangle[row - 1][j]);return Min;}
};

🌭4.求路径


在这里插入图片描述

原题链接:求路径

法一:递归

class Solution {
public:int uniquePaths(int m, int n) {if (m == 1 || n == 1)return 1;return uniquePaths(m - 1, n) + uniquePaths(m, n - 1);}
};

法二:动态规划

在这里插入图片描述

class Solution {
public:int uniquePaths(int m, int n) {if (m == 1 || n == 1)return 1;// 初始化为1vector<vector<int> > a(m, vector<int>(n, 1));for (int i = 1; i < m; i++){// 到达 [i][j] 的路径数 等于 到达[i - 1][j]和到达[i][j - 1]的路径数之和for (int j = 1; j < n; j++)a[i][j] = a[i][j - 1] + a[i - 1][j];}return a[m - 1][n - 1];}
};

法三:公式法

在这里插入图片描述

class Solution {
public:int uniquePaths(int m, int n) {long long ret = 1;for (int i = n, j = 1; j < m; i++, j++)ret = ret * i / j;return ret;}
};

🍿5.带权值的最小路径和


在这里插入图片描述

原题链接:带权值的最小路径和

在这里插入图片描述

在这里插入图片描述

class Solution {
public:int minPathSum(vector<vector<int> >& grid) {int m = grid.size();int n = grid[0].size();//初始化for (int i = 1; i < m; i++)grid[i][0] = grid[i - 1][0] + grid[i][0];for (int i = 1; i < n; i++)grid[0][i] = grid[0][i - 1] + grid[0][i];// 转移方程for (int i = 1; i < m; i++){for (int j = 1; j < n; j++)grid[i][j] = min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j];}return grid[m - 1][n - 1];}
};

🧂6.背包问题


在这里插入图片描述

原题链接:背包问题

在这里插入图片描述

class Solution {
public:int backPackII(int m, vector<int>& A, vector<int>& V) {if (A.empty() || V.empty() || m < 1)return 0;const int N = A.size() + 1;const int M = m + 1;vector<vector<int> > ret;ret.resize(N);// 初始化for (int i = 0; i != N; ++i) {ret[i].resize(M, 0);}for (int i = 1; i < N; i++){for (int j = 1; j < M; j++){// 如果背包总空间都不够放第i个物品,则放 i 个物品和 放 i - 1 个物品的情况相同if (j < A[i - 1])ret[i][j] = ret[i - 1][j];// 如果空间足够放第i个物品,则要判断是否要放入,详见上文解析elseret[i][j] = max(ret[i - 1][j], ret[i - 1][j - A[i - 1]] + V[i - 1]);}}return ret[N - 1][m];}
};

优化算法:

class Solution {
public:int backPackII(int m, vector<int>& A, vector<int>& V) {if (A.empty() || V.empty() || m < 1)return 0;const int M = m + 1; // 包容量const int N = A.size() + 1; // 物品数量vector<int> ret(M, 0);for (int i = 1; i < N; i++){// 上面的算法在计算第i行元素时,只用到第i-1行的元素,所以二维的空间可以优化为一维空间// 但是如果是一维向量,需要从后向前计算,因为后面的元素更新需要依靠前面的元素未更新(模拟二维矩阵的上一行的值)// 并且我们观察到,本行的元素只需要用到上一行的元素,所以从前往后,从后往前都相同// 且用到上一行元素的下标不会超过本行元素的下标for (int j = m; j >= 0; j--){if (j >= A[i - 1])ret[j] = max(ret[j], ret[j - A[i - 1]] + V[i - 1]);}}return ret[m];}
};

🥓7.分割回文串


在这里插入图片描述

原题链接:分割回文串

状态
子状态:到第1,2,3,…,n个字符需要的最小分割数

  • F ( i ) F(i) F(i): 到第i个字符需要的最小分割数

状态递推

  • F ( i ) = m i n F ( i ) , 1 + F ( j ) F(i) = min{F(i), 1 + F(j)} F(i)=minF(i),1+F(j), where j < i && j + 1到i是回文串
  • 上式表示如果从 j+1 到 i 判断为回文字符串,且已经知道从第1个字符到第 j 个字符的最小切割数,那么只需要再切一次,就可以保证1–>j, j+1–>i都为回文串。

初始化

  • F ( i ) = i − 1 F(i) = i - 1 F(i)=i1
  • 上式表示到第i个字符需要的最大分割数,比如单个字符只需要切0次,因为单子符都为回文串,2个字符最大需要1次,3个2次…

返回结果

  • F ( n ) F(n) F(n)
class Solution {
public:// 判断是否为回文字符串bool isPal(string& s, int left, int right){while (left < right){if (s[left] != s[right])return false;left++;right--;}return true;}int minCut(string s) {if (s.empty())return 0;int len = s.size();int* ret = new int[len + 1];// 一个长为 i 的字符串,形成回文字符串,最多要被切 i - 1刀for (int i = 0; i <= len; ++i){// 初始化为每个字符串最多可能被分割的次数ret[i] = i - 1;}for (int i = 2; i <= len; ++i){for (int j = 0; j <= i; j++){// 判断 j + 1 到 i 的字符串是否为回文字符串if (isPal(s, j, i - 1))ret[i] = min(ret[i], ret[j] + 1);}}return ret[len];}
};

上述方法两次循环时间复杂度 O ( n 2 ) O(n ^ 2) O(n2)判断回文串时间复杂度 O ( n ) O(n) O(n) ,所以总时间复杂度 O ( n 3 ) O(n ^ 3) O(n3)

对于过长的字符串,在OJ的时候会出现TLE(Time Limit Exceeded),判断回文串的方法可以继续优化,使总体时间复杂度将为 O ( n 2 ) O(n^2) O(n2)

判断回文串,这是一个“是不是”的问题,所以也可以用动态规划来实现

状态
子状态:从第一个字符到第二个字符是不是回文串,第1-3,第2-5,…

  • F ( i , j ) F(i,j) F(i,j): 字符区间 [i,j] 是否为回文串

状态递推

  • F ( i , j ) F(i,j) F(i,j): true->{ s [ i ] = = s [ j ] s[ i ]==s[j] s[i]==s[j] && F ( i + 1 , j − 1 ) F(i+1,j-1) F(i+1,j1)} OR false
    上式表示如果字符区间首尾字符相同且在去掉区间首尾字符后字符区间仍为回文串,则原字符区间为回文串
  • 从递推公式中可以看到第 i 处需要用到第 i + 1 处的信息,所以 i 应该从字符串末尾遍历

初始化
F ( i , j ) F(i,j) F(i,j) = false

返回结果
矩阵 F ( n , n ) F(n,n) F(n,n), 只更新一半值(i <= j),$n^2 / 2 $

class Solution {
public:vector<vector<bool> > getMat(string& s){int len = s.size();vector<vector<bool> > mat = vector<vector<bool> >(len, vector<bool>(len, false));for (int i = len - 1; i >= 0; --i){// 判断[i , j]范围内是否为回文for (int j = i; j < len; ++j){if (j == i)mat[i][j] = true;else if (j == i + 1)mat[i][j] = (s[i] == s[j]);elsemat[i][j] = ((s[i] == s[j]) && mat[i + 1][j - 1]);}}return mat;}int minCut(string s) {if (s.empty())return 0;int len = s.size();int* ret = new int[len + 1];// 获取回文字符串判断数组vector<vector<bool> > mat = getMat(s);// 一个长为 i 的字符串,形成回文字符串,最多要被切 i - 1刀for (int i = 0; i <= len; ++i){ret[i] = i - 1;}for (int i = 2; i <= len; ++i){for (int j = 0; j <= i; ++j){// 此时判断 j + 1 到 i 的字符串是否为回文字符串,就可以直接从数组中拿if (mat[j][i - 1])ret[i] = min(ret[i], ret[j] + 1);}}return ret[len];}
};

综上,这个算法的时间复杂度被优化到了 O ( n 2 ) O(n^2) O(n2)


🥚8.编辑距离


在这里插入图片描述

原题链接:编辑距离

状态

word1 的前 1,2,3,...m 个字符转换成 word2 的前 1,2,3,...n 个字符需要的编辑距离

  • F ( i , j ) F(i,j) F(i,j): word1 的前 i 个字符于 word2 的前 j 个字符的编辑距离

状态递推

  • F ( i , j ) = m i n F ( i − 1 , j ) + 1 , F ( i , j − 1 ) + 1 , F ( i − 1 , j − 1 ) + ( w 1 [ i ] = = w 2 [ j ] ? 0 : 1 ) F(i,j) = min { F(i-1,j)+1, F(i,j-1) +1, F(i-1,j-1) +(w1[i]==w2[j]?0:1) } F(i,j)=minF(i1,j+1,F(i,j1)+1,F(i1,j1)+(w1[i]==w2[j]?0:1)

上式表示从删除,增加和替换操作中选择一个最小操作数

  • F ( i − 1 , j ) F(i-1,j) F(i1,j): w 1 [ 1 , . . . , i − 1 ] w1[1,...,i-1] w1[1,...,i1] w 2 [ 1 , . . . , j ] w2[1,...,j] w2[1,...,j] 的编辑距离,删除 w 1 [ i ] w1[i] w1[i] 的字符—> F ( i , j ) F(i,j) F(i,j)
  • F ( i , j − 1 ) F(i,j-1) F(i,j1): w 1 [ 1 , . . . , i ] w1[1,...,i] w1[1,...,i] w 2 [ 1 , . . . , j − 1 ] w2[1,...,j-1] w2[1,...,j1] 的编辑距离,增加一个字符—> F ( i , j ) F(i,j) F(i,j)
  • F ( i − 1 , j − 1 ) F(i-1,j-1) F(i1,j1): w 1 [ 1 , . . . , i − 1 ] w1[1,...,i-1] w1[1,...,i1] w 2 [ 1 , . . . , j − 1 ] w2[1,...,j-1] w2[1,...,j1] 的编辑距离,如果 w 1 [ i ] w1[i] w1[i] w 2 [ j ] w2[j] w2[j] 相同,不做任何操作,编辑距离不变,如果 w 1 [ i ] w1[i] w1[i] w 2 [ j ] w2[j] w2[j] 不同,替换 w 1 [ i ] w1[i] w1[i] 的字符为 w 2 [ j ] w2[j] w2[j]—> F ( i , j ) F(i,j) F(i,j)

初始化
初始化一定要是确定的值,如果这里加入空字符串,以便于确定初始化状态

  • F ( i , 0 ) = i F(i,0) = i F(i,0)=i :word与空串的编辑距离,删除操作
  • F ( 0 , i ) = i F(0,i) = i F(0,i)=i :空串与word的编辑距离,增加操作

返回结果 F ( m , n ) F(m,n) F(m,n)

class Solution {
public:int minDistance(string word1, string word2) {if (word1.empty() || word2.empty())return max(word1.size(), word2.size());int len1 = word1.size();int len2 = word2.size();vector<vector<int>> ret(len1 + 1, vector<int>(len2 + 1, 0));// 初始化// j == 0 时for (int i = 0; i <= len1; ++i)ret[i][0] = i;// i == 0 时for (int i = 0; i <= len2; ++i)ret[0][i] = i;for (int i = 1; i <= len1; ++i){for (int j = 1; j <= len2; ++j){// 先选择删除 or 插入ret[i][j] = min(ret[i - 1][j] + 1, ret[i][j - 1] + 1);// 判断是否要替换,如果要替换,操作数 +1 ,反之不变// word1的第 i 个字符,对应索引为i - 1,word2同理if (word1[i - 1] == word2[j - 1])ret[i][j] = min(ret[i - 1][j - 1], ret[i][j]);elseret[i][j] = min(ret[i - 1][j - 1] + 1, ret[i][j]);}}return ret[len1][len2];}
};

🍳9.不同子序列


在这里插入图片描述

原题链接:不同的子序列

状态
子状态:由 S 的前 1,2,...,m 个字符组成的子串与 T 的前 1,2,...,n 个字符相同的个数

  • F ( i , j ) F(i,j) F(i,j) : S[0 ~ i-1] 中的子串与 T[0 ~ j-1] 相同的个数

状态递推
F ( i , j ) F(i,j) F(i,j) 处需要考虑 S [ i − 1 ] = T [ j − 1 ] S[i - 1] = T[j - 1] S[i1]=T[j1] S [ i − 1 ] ! = T [ j − 1 ] S[i - 1] != T[j - 1] S[i1]!=T[j1]两种情况(这里S的第i个字符索引值就是 i - 1 , T同理)

  • S [ i − 1 ] = T [ j − 1 ] S[i-1] = T[j-1] S[i1]=T[j1]:
    1. S [ i − 1 ] S[i - 1] S[i1]匹配 T [ j − 1 ] T[j-1] T[j1],则
      F ( i , j ) = F ( i − 1 , j − 1 ) F(i,j) = F(i-1,j-1) F(i,j)=F(i1,j1)
    2. S [ i − 1 ] S[i - 1] S[i1]不匹配 T [ j − 1 ] T[j - 1] T[j1],则问题就变为 S[0 ~ i-1] 中的子串与 T[0 ~ j-1] 相同的个数,则
      F ( i , j ) = F ( i − 1 , j ) F(i,j) = F(i-1,j) F(i,j)=F(i1,j)
      故, S [ i − 1 ] = T [ j − 1 ] S[i-1] = T[j-1] S[i1]=T[j1]时, F ( i , j ) = F ( i − 1 , j − 1 ) + F ( i − 1 , j ) F(i,j) = F(i-1,j-1) + F(i-1,j) F(i,j)=F(i1,j1)+F(i1,j)
  • S [ i − 1 ] ! = T [ j − 1 ] S[i-1] != T[j-1] S[i1]!=T[j1]:
    问题退化为 S[0 ~ i-2] 中的子串与 T[0 ~ j-1] 相同的个数
    故, S [ i − 1 ] ! = T [ j − 1 ] S[i-1] != T[j-1] S[i1]!=T[j1]时, F ( i , j ) = F ( i − 1 , j ) F(i,j) = F(i-1,j) F(i,j)=F(i1,j)

初始化:引入空串进行初始化

  • F ( i , 0 ) = 1 F(i,0) = 1 F(i,0)=1 —> S的子串与空串相同的个数,只有空串与空串相同

返回结果
F ( m , n ) F(m,n) F(m,n)

class Solution {
public:int numDistinct(string S, string T) {int lenS = S.size();int lenT = T.size();vector<vector<int> > ret(lenS + 1, vector<int>(lenT + 1, 0));// 初始化for (int i = 0; i <= lenS; ++i)ret[i][0] = 1;for (int i = 1; i <= lenS; ++i){for (int j = 1; j <= lenT; ++j){// 判断S的第i个字符是否与T的第j个字符相等// 如相等,可以选择是否使用S的第i个字符,最后结果为 使用S的第i个字符的情况 + 未使用S的第i个字符的情况// 不相等的话,就继承 S的前i - 1个字符 与 T的前j个字符 相同的个数if (S[i - 1] == T[j - 1])ret[i][j] = ret[i - 1][j] + ret[i - 1][j - 1];elseret[i][j] = ret[i - 1][j];}}return ret[lenS][lenT];}
};

我们观察发现 r e t [ i , j ] ret[i , j] ret[i,j] 的取值只与 r e t [ i − 1 , j ] ret[i - 1, j] ret[i1,j] r e t [ i − 1 , j − 1 ] ret[i - 1,j -1] ret[i1,j1] 有关,所以我们可以使用与背包问题类似的优化方法,将空间复杂度优化到 O ( n ) O(n) O(n)

优化算法:

class Solution {
public:int numDistinct(string S, string T) {int lenS = S.size();int lenT = T.size();// 只保留列就可以vector<int> ret(lenT + 1, 0);ret[0] = 1;for (int i = 1; i <= lenS; ++i){// 为了防止上一行的值还没使用就被覆盖,我们必须反着走,从最后一列到第一列for (int j = lenT; j >= 1; --j){if (S[i - 1] == T[j - 1])ret[j] = ret[j] + ret[j - 1];elseret[j] = ret[j];}}return ret[lenT];}
};

🍉总结


  • 动态规划状态定义

    • 状态来源:从问题中抽象状态

    • 抽象状态:每一个状态对应一个子问题

    • 状态的定义可以有很多种,但是如果验证状态定义的合理性呢?

      1. 某一个状态的解或者多个状态处理之后的解能否对应最终问题的解。
      2. 状态之间可以形成递推关系
    • 一维状态 or 二维状态?

      依据题目对象找线索。

      首先尝试一维状态,一维状态不合理时,再定义二维状态。

    • 常见问题的状态:

      • 字符串:状态一般对应子串,状态中每次一般增加一个新的字符。
      • 矩阵:二维状态(在只用到上一行的数据时,可能可以被优化成一维状态)

注意:动态规划中,最重要的一步就是状态的定义,如果状态定义不合理,会带来很多麻烦。


这是一个新的系列 ——【刷题日记】,白晨开这个系列的初衷是为了分享一些经典题型,以便于大家更好的学习编程。

如果解析有不对之处还请指正,我会尽快修改,多谢大家的包容。

如果大家喜欢这个系列,还请大家多多支持啦😋!

如果这篇文章有帮到你,还请给我一个大拇指 👍和小星星 ⭐️支持一下白晨吧!喜欢白晨【刷题日记】系列的话,不如关注👀白晨,以便看到最新更新哟!!!

我是不太能熬夜的白晨,我们下篇文章见。


http://chatgpt.dhexx.cn/article/t2jwusER.shtml

相关文章

Linux命令-sftp文件传输

搭建SFTP服务详见博文&#xff1a;https://blog.csdn.net/cen50958/article/details/90722874 连接SFTP 可使用&#xff1a;sftp --help 查看SFTP的连接参数 [rootstudy ~]# sftp --help usage: sftp [-1Cv] [-B buffer_size] [-b batchfile] [-F ssh_config] [-o ssh_option…

Linux命令(三):SFTP

目录 1、登录 2、文件上传 3、文件下载 4、删除文件/文件夹 5、实战 1、登录 sftp userip 你要用sftp, 当然得登录到sftp服务器&#xff0c; 在linux的shell中执行上面的命令后&#xff0c; linux shell会提示用户输入密码&#xff0c; 我们就输入password吧。 这样就成功…

Linux常用命令——sftp命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) sftp 交互式的文件传输程序 补充说明 sftp命令是一款交互式的文件传输程序&#xff0c;命令的运行和使用方式与ftp命令相似&#xff0c;但是&#xff0c;sftp命令对传输的所有信息使用ssh加密&#xff0c;它还…

SFTP命令常用操作

SFTP相关(等价于rz/sz&#xff0c;此方式适用于没有工具的情况下&#xff0c;前提是保证sftp默认端口22开放) lcd 本地文件路径 进入到本地的某个目录下 cd 远程文件路径 进入到远程的某个目录下 lpwd 显示本地的当前目录的路径 pwd 显示远程的当前目录的路径 这里只介绍常…

SFTP基本功之get、put命令操作

简述 在安装好linux系统之后&#xff0c;开始不断安装部署各种工具&#xff0c;其中很多工具版本太老使得无法使用wget下载&#xff0c;而只能用put命令从本地硬盘中上传之linux系统内安装&#xff0c;而当我编写系统克隆mongodb数据库时&#xff0c;又了解到了get命令&#x…

SFTP命令的使用,sftp传文件

背景&#xff1a;从Windows系统向类unix系统传送文件&#xff0c;使用Windows系统自带的SFTP命令进行文件传送(不用下载F开头&#xff0c;X开头的ftp工具) 背景分割线 上干货&#xff1a;1.WinX&#xff0c;按A&#xff0c;输入SFTP root192.168.162.236 回车&#xff1b; &…

SFTP登录及命令行用法

sftp命令行登录过程 ① sftp xxx.xxx.xxx.xxx 登录&#xff08;默认root用户&#xff09;&#xff0c;若指定用户 sftp bluexxx.xxx.xxx.xxx 进行登录&#xff08;blue为用户名&#xff09; ② 登录成功后&#xff0c;会提示输入 密码 ③ 然后&#xff0c;可进入目录&#xf…

SFTP命令用法(上传和下载 )

一、SFTP SFTP是Secure File Transfer Protocol的缩写&#xff0c;安全文件传送协议。可以为传输文件提供一种安全的网络的加密方法。SFTP与FTP有着几乎一样的语法和功能。SFTP为SSH的其中一部分&#xff0c;是一种传输档案至Blogger伺服器的安全方式。其实在SSH软件包中&…

Linux基础命令 sftp命令的使用

SFTP&#xff08;Secure File Transfer Protocol&#xff0c;安全文件传输协议&#xff09;是一种基于可靠数据流&#xff08;data stream&#xff09;&#xff0c;提供文件存取和管理的网络传输协议&#xff0c;与 FTP 协议相比&#xff0c;SFTP 在客户端与服务器间提供了一种…

sftp常用命令介绍

sftp常用命令&#xff1a; 1. sftp 登录sftp服务器 sftp userip ​​​​​​ 如需要看全部命令&#xff1a;则使用help即可 2. pwd和lpwd 、 ls和lls 、cd和lcd 等 sftp登录之后默认操作是远程服务器&#xff0c;当需要操作本地时&#xff0c;就需要在前边加“l”&#…

Linux中使用sftp的常用命令

前言 在数据库远程维护的过程中&#xff0c;经常需要和本机进行数据的交互&#xff0c;常用的交互方式为ftp&#xff0c;但是这种方式需要确保21端口和ftp服务都存在。在远程访问服务器的时候大部分使用ssh来进行连接&#xff0c;其使用的端口为22端口&#xff0c;与之共用的数…

单链表的基本操作-查找

【问题描述】 实现有头结点单链表查找算法&#xff1a;根据关键字值查找其在单链表中的位置(第一次出现的位置)。 【输入形式】 第一行输入整数n&#xff08;n不大于1000&#xff09;&#xff0c;表示单链表长度&#xff1b; 第二行输入若干个整数&#xff08;以非法整数或…

单链表的基本操作(C语言+图解分析)

目录 一、单链表的建立 1、头插法 2、尾插法 二、插入结点操作 三、删除节点操作 四、单链表操作的一些常见问题 1、结构体变量和结构体指针的区别&#xff1f; 2、什么时候要malloc&#xff1f; 3、形参里面出现了取地址符(&)&#xff0c;有什么作用&#xff1f;…

c++单链表的基本操作(全)

俩个基本插入方法 #include <bits/stdc.h> using namespace std; typedef struct LNode { int date; //节点的数据域 struct LNode *next; //节点的指针域 }LNode,*LinkList; // LinkList 为指向结构体LNode的指针类型bool Initlist_L(LinkList &L) …

单链表的基本操作(学习总结)

单链表的声明初始化&#xff1a; 1.头文件&#xff1a; 这里不做太多说明&#xff0c;是学习C语言的基础。 #include<stdio.h> #include<stdlib.h> 2.结构声明&#xff1a; 数据结构算法中&#xff0c;每个表&#xff0c;树&#xff0c;图类的工具组都需要定义它…

Java 实现单链表的基本操作

顺序表&#xff1a;物理上逻辑上都连续&#xff1b; 链表&#xff1a;物理上不一定连续&#xff0c;逻辑上一定连续的。 链表的概念及结构 概念&#xff1a;连表示一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是用过链表中的引用链接次序实现的…

数据结构:单链表的基本操作

单链表是一种链式存取的数据结构&#xff0c;用一组地址任意的存储单元存放线性表中的数据元素。这组存储单元可以是连续的&#xff0c;也可以是不连续的。链表中的数据是以结点来表示的&#xff0c;一个结点包含数据域和指针域&#xff0c;数据域用来存储结点的值&#xff0c;…

python实现单链表的基本操作

一、单链表 单向链表&#xff08;单链表&#xff09;是链表的一种&#xff0c;其特点是链表的链接方向是单向的&#xff0c;对链表的访问要通过顺序读取从头部开始。单链表是一种链式存取的数据结构&#xff0c;用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是…

Java实现单链表及其基本操作

目录 什么是单链表&#xff1f; 带头结点的单链表 不带头结点的单链表 模拟实现不带头结点的单链表 定义结点类 初始化 头插法创建单链表 尾插法创建单链表 打印单链表 单链表的查找 获取单链表的长度 按位置寻找前驱结点 单链表的插入 修改指定位置的值 按…

【数据结构】二、单链表的基本操作(C语言)

目录 引用头指针的好处&#xff1a; 1.结点的定义和初始化单链表 2.判断单链表是否为空表 3.销毁单链表 4.清空单链表&#xff0c;头结点和头指针还在 5.求单链表表长 6.取单链表中指定位置的数据 7.按值查找,返回数据所在的地址&#xff0c;时间复杂度为O(n)​编辑…