【ONE·基础算法 || 记忆化搜索】

news2024/10/7 14:32:37

在这里插入图片描述

总言

  主要内容:编程题举例,熟悉理解记忆化搜索类题型(对比递归、动态规划理解运用)。
  
  
  
  

文章目录

  • 总言
  • 1、记忆化搜索
    • 1.1、基本介绍
    • 1.2、细节理解(记忆搜索化、递归、动态规划……)
  • 2、斐波那契数(easy)
    • 2.1、递归版
    • 2.2、记忆化搜索版
    • 2.3、动态规划版
  • 3、不同路径(medium)
    • 3.1、递归版(DFS)
    • 3.2、记忆化搜索版
    • 3.3、动态规划版
  • 4、最长递增子序列(medium)
    • 4.1、记忆化搜索版
    • 4.2、动态规划版
  • 5、猜数字大小II(medium)
    • 5.1、题解
  • 6、矩阵中的最长递增路径(hard)
    • 6.1、题解
  • Fin、共勉。

  
  
  
  
  

1、记忆化搜索

1.1、基本介绍

  1)、记忆搜索化是什么?主要用来解决什么问题的?
  为了探究记忆搜索化的用途,我们以下述第一道题:斐波那契数为例,进行说明。

  递归版的斐波那契数写法见下述:由递归展开图可知,假如我们要计算 d ( 5 ) d(5) d(5),则需要先计算 d ( 4 ) d(4) d(4) d ( 3 ) d(3) d(3),而在计算 d ( 3 ) d(3) d(3) 时还需要计算 d ( 2 ) d(2) d(2) d ( 1 ) d(1) d(1) 。这会带来一个问题: d ( 4 ) d(4) d(4) d ( 3 ) d(3) d(3) d ( 2 ) d(2) d(2) d ( 1 ) d(1) d(1) 都进行了多次计算,即出现了大量重复计算的子问题。

在这里插入图片描述

  那么,有什么方法对其进行优化?
  
  回答:为了避免此类重复计算,在递归时,我们可以使用一个备忘录(本质是一个数组或哈希表)来保存已经计算过的状态及其对应的结果。 这样,在后续递归过程中,每次调用可先检查一下所需的结果是否已经被计算并保存过? 若是,则直接从备忘录中返回所需结果;若否,则进行递归计算,同时将结果保存在备忘录中,以便后续使用。如此,就避免了重复计算问题。(也可以把它理解为一种剪枝操作)

在这里插入图片描述

  这也就是记忆搜索化。一种结合了搜索和动态规划思想的算法策略。其核心思想是在搜索过程中,对于已经计算过的状态或子问题的解进行保存,当再次遇到相同的状态或子问题时,直接使用之前保存的结果,从而避免重复计算,提高算法效率。
  
  
  
  
  2)、如何实现记忆搜索化?(一般性流程步骤 )

  1、在常规的递归基础上,添加一个备忘录 (一个哈希表或数组,用于存储已经计算过的子问题的结果,以<参数,返回值>的键值对形式)
  2、递归每次返回的时候,将结果放到备忘录里面。
  3、在每次进入递归的时候,先检查备忘录里面是否存在所需计算结果。

  
  
  
  
  
  

1.2、细节理解(记忆搜索化、递归、动态规划……)

  1)、 所有的递归(暴搜、 深搜) ,都能改成记忆化搜索吗?
  回答:不是,只有在递归的过程中,出现了大量完全相同的问题时,才能用记忆化搜索的方式优化。

  ①记忆化搜索的优化效果主要体现在能够避免重复计算相同的子问题。 因此,只有当递归过程中存在大量重复的子问题,即 “子问题重叠”现象时,采用记忆化搜索才是有意义的。
  ②如果递归算法中的子问题都是唯一的,或者重复的子问题数量很少,那么使用记忆化搜索可能并不会带来明显的性能提升,甚至可能由于记忆化存储结构的开销而降低效率。
  
  
  

  2)、 动态规划 与 记忆化搜索
  本质: ①均属于暴力解法(暴搜),②不过在其基础上进行了一定的优化(通过把已经计算过的值存起来的方式)。
  实际上,《算法导论》中,将记忆化搜索与常规的动态规划都视为动态规划的一种形式,只是前者搜索时是以递归的方式进行的,而后者则是递推(循环)的方式。
  
  实际写代码时,选哪种方式好?
  在实际编写代码时,选择自顶向下(记忆化搜索)还是自底向上(动态规划)的方式取决于多个因素,包括问题的特性、代码的可读性、性能需求以及个人的编程习惯。
  (暴搜→记忆化搜索→动态规划)在优化级别上,在很多情况下,将暴力搜索(暴搜)优化为记忆化搜索已经足够满足性能需求,而且这样的优化通常比完全重写为动态规划版本更加简单和直接。因此,在实际应用中,如果记忆化搜索已经足够好,那么可能没有必要再进一步将其改写为动态规划版本。
  
  
  

  3)、 带备忘录的递归 vs 带备忘录的动态规划 vs 记忆化搜索
  回答:根据2)可知,它们本质都是一回事。都利用了“记忆”或“存储”已经计算过的结果来避免重复计算,从而提高算法效率。只不过,它们在实现和应用上存在细节上的差别。
  
  
  

  4)、 自顶向下和 vs 自低向上
  自顶向下和自底向上的方法代表了两种不同的思考策略,它们的核心区别在于处理问题的顺序

  自顶向下(Top-Down) 方法通常从问题的最高层次(即整体或宏观层面)开始,逐步细化到更低层次的具体细节。这种方法的一个典型例子是递归算法和记忆化搜索。 在递归算法中,我们首先尝试解决整个问题,然后将其分解为更小的子问题。如果子问题已经被解决过(通过记忆化),则直接返回结果;否则,递归地解决子问题。这种方法的优势在于直观易理解,但如果不加记忆化,可能会导致大量的重复计算。
  
  自底向上(Bottom-Up) 方法则相反,它从问题的最低层次(即微观层面)开始,逐步构建出更高层次的解决方案。动态规划是这种方法的典型代表。 在动态规划中,我们首先解决所有可能的子问题,并将它们的解存储在表格或数组中。然后,通过组合这些子问题的解来构建出原问题的解。这种方法避免了重复计算,但可能需要更多的存储空间来保存中间结果。
  
  
  
  
  
  
  
  

2、斐波那契数(easy)

  题源:链接。

在这里插入图片描述
  
  

2.1、递归版

  1)、一些说明
  在上述我们介绍过记忆化搜索、递归相关理论部分的知识,这里是具体实现(动态规划相关专题会另写博文介绍,这里不做展开)。
  下述版本重点在于理解递归版如何到记忆化搜索版,理解学习记忆化搜索的具体实现细节,对比递归版理解自顶向下和自底向上。
  
  2)、题解

class Solution {
    
public:
    int fib(int n) {
        return DFS(n);
    }

    // 使用递归的方式
    int DFS(int n)
    {
        if(n == 0 || n == 1)
            return n;

        return DFS(n-1) + DFS(n-2);
    }
};

  
  
  
  

2.2、记忆化搜索版

  a、 加上⼀个备忘录;
  b、 每次进⼊递归的时候,去备忘录里看看;
  c、 每次返回的时候,将结果加入到备忘录中

class Solution {
    // 使用一个备忘录:用于存储曾经获取的结果值
    int memo[31];// 题目条件:0 <= n <= 30
    
public:
    int fib(int n) {
        memset(memo,-1,sizeof(memo));//void * memset ( void * ptr, int value, size_t num );
        return DFS(n);
    }
    
    // 记忆化搜索版
    int DFS(int n)
    {
        // 递归到当前层时:先查找备忘录,看该值是否已经计算过
        if(memo[n] != -1) return memo[n];

        // 来到此处,说明备忘录中没记录过该值,可以递归计算
        if(n == 0 || n == 1)
        {
            memo[n] = n;// 递归返回前,先将数据记录入备忘录中
            return n;
        }

        memo[n] = DFS(n-1) + DFS(n-2);// 递归返回前,先将数据记录入备忘录中
        return memo[n];
    }
};

  
  
  
  

2.3、动态规划版

  无非是将递归的那一套转换成了动态规划的那一套(这种先暴搜→再记忆化搜索→再改为动态规划的方式,不是任何动态规划都能用这个思路推导得出的。
  a、递归含义 → 状态表示;
  b、函数体 → 状态转移方程;
  c、递归出口 → 初始化。

class Solution {
public:
	// 动态规划版
    int fib(int n) {

        int dp[31];// 确定状态表示:dp[i]第i个斐波那契数
        dp[0] = 0, dp[1] = 1;// 初始化状态

        for(int i = 2; i <= n; ++i)
        {
            dp[i] = dp[i-1] + dp[i-2];//根据状态转移方程,填入数据
        }

        return dp[n];// 确定返回值。
    }
};

  
  
  
  
  
  
  
  
  
  

3、不同路径(medium)

  题源:链接。

在这里插入图片描述
  
  

3.1、递归版(DFS)

  1)、思路分析
在这里插入图片描述

  在普通递归版本中: 将要求位置传入递归函数中DFS(i,j),不管其过程如何,最终会为我们返回到达(i,j)位置的路径总数:有DFS(i,j) = DFS(i-1,j) + DFS(i, j-1)
  
  
  
  2)、题解
  简单的DFS、递归: 能解,但会超时。
  这种是正着的写法,上述思路解析介绍的是倒着的写法。

class Solution {
    int ret = 0;// 记录最终返回结果
    int x;
    int y;
public:
    int uniquePaths(int m, int n) {
        x = m -1, y = n-1;//下标实则为m-1,n-1
        DFS(0,0);// 从(0,0)开始,向右或向下,走到(m-1,n-1)位置
        return ret;
    }

    void DFS(int i, int j)
    {   
        // 若当前i,j位置即终点位置,统计一次路径。
        if(i == x && j == y)
        {
            ++ret;
            return;
        }

        // 向右遍历
        if(j+1 <= y) DFS(i,j+1);
        // 向下遍历
        if(i+1 <= x) DFS(i+1,j);
    }
};

  另一种写法:本质一样,只是这里是DFS采用了返回值的形式。

class Solution {

public:
    int uniquePaths(int m, int n) {
        return DFS(m-1,n-1);
    }

    int DFS(int i, int j)
    {
        
        if(i < 0 || j < 0) return 0;// 越界的情况
        if(i == 0 && j == 0) return 1;// 此时在起点位置,路径只有一条


        // 要计算当前能到达(i,j)位置的路径,只需要计算出能到达(i-1,j)和(i,j-1)两处的路径即可
        return DFS(i-1,j) + DFS(i,j-1);
    }
};

  
  
  

3.2、记忆化搜索版

  1)、分析
  能否将上述暴搜改为记忆化搜索版本?关键在于递归过程中是否出现重复的子问题。
  回答:可以改成记忆搜索化版本。这里在求终点的路径时,自顶向下递归调用过程中,会多次经过同一位置DFS(a,b)。因此,我们可以用一个备忘录将每次经过的DFS(a,b)存储,以便后续递归调用时直接返回。
在这里插入图片描述
  由于这里是二维数组(i,j),而备忘录以<可变参数,返回值>的键值对形式出现,这里的可变参数是元素下标位置。
  

  
  
  2)、题解
  这里,用于充当备忘录的二维数组memo可以写成类成员变量的形式,也可以写在函数中作为参数传递。

class Solution {
    vector<vector<int>> memo;
public:
    int uniquePaths(int m, int n) {
        // 初始化
        memo = vector<vector<int>>(m,vector<int>(n));// 这里我们从(0,0)作为原点计算。
        memo[0][0] = 1;
        return DFS(m-1,n-1);
    }

    int DFS(int i, int j)
    {
        // 越界处理
        if(i < 0 || j < 0) return 0;

        if(memo[i][j] != 0)// 记忆化搜索:先在备忘录中寻找当前值是否曾经计算过。
        {
            return memo[i][j];
        }

        // 要计算当前能到达(i,j)位置的路径,只需要计算出能到达(i-1,j)和(i,j-1)两处的路径即可
        memo[i][j] = DFS(i,j-1) + DFS(i-1,j);// 记忆化搜索:返回前,先将值存入备忘录
        return memo[i][j];
    }
};

  
  
  
  
  

3.3、动态规划版

  状态表示:二维数组,dp[i][j],以(i,j)位置为结尾,表示到达(i,j)位置时的路径总数。
  状态转移方程:dp[i][j] = dp[i-1][j] + dp[i][j-1]
  细节点:这里需要注意 i == 0 (首行)或者 j == 0 (首列)的时候,会发生越界行为。 根据题目描述可推测得,从(0,0)到这些位置无非只有一条路径可走(要么一直往右走、要么一直往下走),因此,对于这一行一列,可以单独拎出处理:dp[i][j] = 1

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m, vector<int>(n));//m×n矩阵
        dp[0][0] = 1 ;// 起始点位置:这里以(0,0)为起点
        for(int i = 0; i < m; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(i == 0 && j == 0) continue;
                if(i == 0 || j == 0) dp[i][j] = 1;
                else
                    dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[m-1][n-1];//根据最初定的起点来确定终点
    }
};

  若不想初始化处理首行、首列。此时要避免越界行为,可以开辟(m+1)×(n+1)的矩阵,以(1,1)位置作为起始点。相当于此时i == 0的行和j==0的列是空出来的(引入虚拟节点的写法):

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));// m+1行,n+1列矩阵
        dp[1][1] = 1;// 起始点位置:这里以(1,1)为起点
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++) {
                if (i == 1 && j == 1)
                    continue;
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];//实则本质相同,在处理首行、首列时,仍旧只是一条路径
            }
        return dp[m][n];
    }
}

  
  
  
  
  
  
  

4、最长递增子序列(medium)

  题源:链接。

在这里插入图片描述  
  

4.1、记忆化搜索版

  1)、思路分析
  
在这里插入图片描述

  
  2)、题解

class Solution {
    vector<int> memo;// 备忘录:用于记忆化搜索
public:
    int lengthOfLIS(vector<int>& nums) {
        memo.resize(nums.size());
        int maxsize = 0;
        for(int i = 0; i < nums.size(); ++i)
        {
            maxsize = max(DFS(nums,i),maxsize);
            // 不确定以哪一个位置为起点才是最长的递增子序列,因此这里要一一对比一边
        }
        return maxsize;
    }

    // pos位置的元素为子序列上一层选定的序列值
    int DFS(vector<int>& nums, int pos)
    {
        // 若当前选择pos的最大子序列曾记录在备忘录内,则直接获取返回
        if(memo[pos]) return memo[pos];

        // 若备忘录中无记录,则递归查找当前最大子序列
        int maxsize = 1;// 选择下一层递归序列值:pos位置处的决策可以有很多分支,我们只要其中长度最大的分支
        for(int i = pos + 1; i < nums.size(); ++i)
        {   
            if(nums[i] > nums[pos])// 满足严格递增,可选该值
            {
                int ret =  DFS(nums,i) + 1;// 获取从该值往下递归的结果+将当前pos也算入
                maxsize = max(ret,maxsize);// 只记录最大子序列
            }
        }
        memo[pos] = maxsize;// 将当前pos选出的最大子序列记录入备忘录中
        return memo[pos];
    }
};

  
  
  
  

4.2、动态规划版

  1)、思路分析
  确定状态表示: dp[pos]表示以pos位置为起点的最长递增子序列长度。
  填表顺序: 根据题目,要确定当前pos位置的序列,需要依赖[pos+1, n-1]区间内的元素。因此,这里的填表顺序为从后往前填。
  状态转移方程: dp[pos] = max(dp[pos], dp[pos + i] + 1)。由于一个位置处的子序列有多个,而dp[pos]只需要最长递增子序列,因此这里实则是要遍历[pos+1, n-1],比较获取其中最长的递增序列长度,+1即可获得到当前序列的最长长度。
  
  2)、题解

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        // 动态规划
        int n = nums.size();
        vector<int> dp(n,1);// 初始化状态表示:自身位置处序列个数为1

        int maxsize = 0;// 用于统计最长子序列

        // 根据题目,要知道i位置处的最长子序列,则需要知道其后续[i+1,n)位置处的子序列(即,i后应该选谁)
        for(int i = n-1; i >= 0; --i)///所以这里的填表顺序是从右到左
        {
            for(int j = i + 1 ; j < n; ++j)//找[i+1,n)中最长的子序列,+i位置即可获取i处最长子序列
            {
                if(nums[j] > nums[i])
                {
                    dp[i] = max(dp[i],dp[j] + 1);
                }
            }
            maxsize  = max(dp[i],maxsize);//dp[i]统计的是i位置处的最长子序列,maxsize记录的是0~n-1中最长子序列
        }
        return maxsize;
    }
};

  
  
  
  
  
  
  

5、猜数字大小II(medium)

  题源:链接。

在这里插入图片描述
  
  

5.1、题解

  1)、思路分析
  此时实则在模拟猜数字的过程。可将整体分为如下:
  1)、对[1,n]个数,在猜数字时可以随机选择其中任意一个数字作为起始决策值。由此,可获得n棵决策树。当我们选择不同的策略,最终花费的金额各不相同,根据题目要求,要选出能获胜的最小现金数,这就意味着我们要在所有决策树中找最优解(金额最小的决策树)
在这里插入图片描述

  2)、对单棵决策树,由于题目中目标数字是随机的,我们要保证无论给定的是哪一个目标值(即无论哪一条分支),我们的金额都能支付得起,如此才能胜券在握。这就意味着我们要支付的金额为当前单棵决策树的分支最大值。
在这里插入图片描述
  
  是否可以使用记忆化搜索?
  如下图,在递归过程中,每次选出一个数i,若其不满足目标值,则需要在左右区间选数,这里区间[left,right]在选数时会出现重复,故可以使用备忘录。只不过这里备忘录我们记录的是左右两区间,故需要一个二维数组。
在这里插入图片描述

  
  
  2)、题解

class Solution {
    vector<vector<int>> memo;// 备忘录
public:
    int getMoneyAmount(int n) {
        memo = vector<vector<int>>(n+1,vector<int>(n+1,0));
        return DFS(1,n);
    }

    // 在区间为[left,right]中,选择位置选择一个数,作为决策树的起始位置
    int DFS(int left, int right)
    {
        if(left >= right)
        {
            return 0;// 选中数字(猜对),无需支付金额;
        }
        if(memo[left][right]) return memo[left][right];

        int minmoney = INT_MAX;// 用于记录所有决策树方案中,所得金额最小的决策方案(因为要是最小值,所以用INT的最大值标记一下)
        for(int i = left; i <= right; ++i)// 选择数i作为起始决策位置
        {
            int x = DFS(left,i-1);// 若数i猜大了:在[left,i-1]继续选数
            int y = DFS(i+1,right);// 若数i猜小了:在[i+1,right]继续选数
            int ret = max(x,y) + i;// 对单颗决策树,要确保金额能满足即使最糟糕情况也能获胜(故而选择最大分支值+还需要加上当前i位置的金额值)
            minmoney = min(minmoney, ret);// 对所有决策树,选择一个使用金额最小的决策方案。
        }
        memo[left][right] = minmoney;
        return minmoney;
    }
};

  
  
  
  
  
  
  
  
  

6、矩阵中的最长递增路径(hard)

  题源:链接。

在这里插入图片描述

  
  

6.1、题解

  1)、思路分析
  此题即常规的DFS+一个备忘录。DFS遍历四周的方法我们在先前章节中介绍过,可以使用备忘录是因为对于每个位置(i,j),都有反复经过的可能,因此使用一个二维数组作为备忘录,memo[i][j]表示在[i][j]位置处的最长递增路径长度。
  
  2)、题解

class Solution {
    int memo[201][201];
    int m,n;
public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        m = matrix.size(); n = matrix[0].size();
        int ret = 0;//用于记录所有起始点中,最长的一条路径。
        for(int i = 0; i < m; ++i) // 选择某一点作为路径起始点
        {
            for(int j = 0; j < n; ++j)
            {
                ret = max(DFS(matrix,i,j),ret);
            }
        }
        return ret;
    }

    int dx[4] = {-1, 1, 0, 0};
    int dy[4] = {0, 0, -1, 1};
    int DFS(vector<vector<int>>& matrix, int i, int j)
    {
        //  如果备忘录中记录过(i,j)位置的最长递增路径,直接返回
        if(memo[i][j] != 0) return memo[i][j];

        // 若没记录过,则向四周移动寻找最长递增路径
        int maxpath = 1;// 用于统计这四个方向中,路径递增且最长的一次
        for(int k = 0; k < 4; ++k)
        {
            int x = i + dx[k]; 
            int y = j + dy[k];
            if(x >= 0 && x < m && y >= 0 && y < n && matrix[x][y] > matrix[i][j])
            {   // 路径合法,且严格递增,则往该方向继续走
                maxpath = max(DFS(matrix,x,y)+1, maxpath);
            }
        }
        // 来到此处,说明四周均判断完毕,记录当前(i,j)找出的最长递增路径,返回
        memo[i][j] = maxpath;
        return maxpath;
    }
};

  
  
  
  
  
  
  
  
  
  
  
  
  

Fin、共勉。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1834060.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何通过小猪APP分发轻松实现Web封装APP

你有没有想过将你的网站或者Web应用变成一个真正的APP&#xff1f;这听起来可能有点复杂&#xff0c;但其实在今天的技术环境下&#xff0c;这已经变得非常简单了。特别是有了像小猪APP分发这样的工具&#xff0c;你可以轻松地将你的Web应用封装成一个APP。 为什么要将Web应用封…

Java学习55-super关键字的使用

1.举例1&#xff1a;子类继承父类以后&#xff0c;对父类方法进行了重写&#xff0c;那么在子类中&#xff0c;是否还可以对父类中被重写的方法进行调用&#xff1f; 可以&#xff01; 举例2&#xff1a;子类继承父类以后&#xff0c;发现子类和父类中定义了同名的属性&#xf…

示例:WPF中在没有MouseDoubleClick的控件中如何识别双击

一、目的&#xff1a;由于MouseDoubleClick控件是在Control中实现&#xff0c;那么在底层控件如Grid中想要类似功能如何实现&#xff0c;这里通过MouseDown的事MouseButtonEventArgs参数去实现 二、实现 定义Grid并注册Grid的MouseDown事件 <Grid Background"Transpa…

Android如何简单快速实现RecycleView的拖动重排序功能

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 要实现这个拖动重排序功能&#xff0c;主要是用到了RecycleView的ItemTouchHelper类 首先是定义一个接口 interface ItemTouchHelperAdapter …

哈尔滨等保测评如何办理

随着人们对网络安全的认识日益加深&#xff0c;越来越多的企业和组织开始重视网络安全等级保护工作。在哈尔滨地区&#xff0c;为了保证网络的安全&#xff0c;等保测评是保障网络安全的重要一环。本文对哈尔滨等保测评的流程、测评具体内容以及注意事项进行了详细地阐述。 一…

0X0-基于Sklearn的机器学习入门:聚类(上)

本节及后续章节将介绍深度学习中的几种聚类算法&#xff0c;所选方法都在Sklearn库中聚类模块有具体实现。本节为上篇&#xff0c;将介绍几种相对基础的聚类算法&#xff0c;包括K-均值算法和均值漂移算法。 目录 X.1 聚类概述 X.1.1 聚类的种类 X.1.2 Sklearn聚类子模块 …

纯css实现炫光流彩Button

正文 先看效果 实现思路 不仔细看的话还以为只需要通过animation与text-shadow、box-shadow、background-image就可以实现 仔细看的话会发现&#xff0c;其实按钮的颜色不是简单的渐变&#xff0c;而是从一侧颜色开始变化&#xff0c;渐渐的颜色蔓延到另一侧&#xff0c;之后…

【机器学习】第10章 聚类算法

一、概念 1.聚类 &#xff08;1&#xff09;是无监督学习&#xff0c;其实无监督学习就是无中生有&#xff0c;不给你标准答案&#xff08;标签啊啥的&#xff09;&#xff0c;然后让你自己来。 &#xff08;2&#xff09;聚类就是这样&#xff0c;让机器自己根据相似特征把相…

WACV2024 分割相关论文摘要小结速览67篇

WACV2024 分割相关论文摘要小结速览 Paper1 Robust Source-Free Domain Adaptation for Fundus Image Segmentation 摘要小结: 无监督域自适应&#xff08;UDA&#xff09;是一种学习技术&#xff0c;它将源域中从标记训练数据学习到的知识转移到只有未标记数据的目标域。这对…

星际航行概论分享

作者最近看到了一篇钱学森的著作《星际航行概论》 PDF格式下载&#xff1a; 星际航行概论.pdf: https://url83.ctfile.com/f/45573183-1272939884-48f07e?p7526 (访问密码: 7526)

【GlobalMapper精品教程】085:coverage格式转shp案例教程

文章目录 一、Coverage格式介绍二、globalmapper转换shp1. 加载coverage2. coverage转shp一、Coverage格式介绍 Coverage 是一种用于存储矢量数据的地理相关数据模型,它包含地理要素的空间(位置)数据和属性(描述性)数据。Coverage 使用一组要素类来表示地理要素。每个要素…

【包管理】Node.JS与Ptyhon安装

文章目录 Node.JSPtyhon Node.JS Node.js的安装通常包括以下几个步骤&#xff1a; 访问Node.js官网&#xff1a; 打开Node.js的官方网站&#xff08;如&#xff1a;https://nodejs.org/zh-cn/download/&#xff09;。 下载安装包&#xff1a; 根据你的操作系统选择对应的Node…

在Windows环境下设置定时任务(任务计划程序)(Python)

文章目录 前言一、准备执行的test.py文件二、准备test.bat批处理文件&#xff08;系统环境变量&#xff09;三、设置定时任务&#xff08;任务计划程序&#xff09; 前言 计划任务是系统的常见功能&#xff0c;利用任务计划功能&#xff0c;可以将任何脚本、程序或文档安排在某…

《Windows API每日一练》4.5 GDI映射模式

上一节讲述设置绘图模式时&#xff0c;包括设置背景模式、混合模式&#xff0c;还有一个就是映射模式。本节我们将详细讲述映射模式。 本节必须掌握的知识点&#xff1a; 设备坐标和逻辑坐标 视口和窗口 MM_TEXT映射模式 度量映射模式 自定义映射模式 第27练&#xff1a;GDI映…

Aigtek高压放大器在柔性爬行机器人驱动性能研究中的应用

实验名称&#xff1a;柔性爬行机器人的材料测试 研究方向&#xff1a;介电弹性体的最小能量结构是一种利用DE材料的电致变形与柔性框架形变相结合设计的新型柔性驱动器&#xff0c;所谓最小能量是指驱动器在平衡状态时整个系统的能量最小&#xff0c;当系统在外界的电压刺激下就…

归并排序个人见解

归并排序个人见解 思路实现代码实现题目 思路实现 归并排序属于分治算法&#xff0c;分治算法有三个步骤&#xff1a; 分&#xff1a;将问题划分为多个规模较小的子问题&#xff0c;这些子问题与原始问题相似。治&#xff1a;递归地解决这些子问题。如果子问题足够小&#xf…

【WEB前端2024】3D智体编程:乔布斯3D纪念馆-第42课-多人联机-实时互动

【WEB前端2024】3D智体编程&#xff1a;乔布斯3D纪念馆-第42课-多人联机-实时互动 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界…

【JVM结构、JVM参数、JVM垃圾回收】

JVM&#xff1a;Java Virtual Machine java虚拟机 虚拟机&#xff1a;使用软件技术模拟出与具有完整硬件系统功能、运行在一个隔离环境中的计算机系统。 JVM官方文档&#xff1a;https://docs.oracle.com/javase/specs/jvms/se8/html/index.html java 一些命令 javac 将文件编…

【Netty】nio处理acceptreadwrite事件

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Netty ⛺️稳中求进&#xff0c;晒太阳 1.处理accept 1.1客户端代码 public class Client {public static void main(String[] args) {try (Socket socket new Socket("localhost…

秋招突击——6/16——复习{整理昨天的面试资料}——新作{删除链表倒数第n个节点}

文章目录 引言复习新作删除链表倒数第N个节点题目描述个人实现参考实现 总结 引言 主管面&#xff0c;面的很凄惨&#xff0c;不过无所谓了&#xff0c;我已经尽力了。上午都在整理的面经&#xff0c;没有复习算法&#xff0c;而且这两天要弄一下论文&#xff0c;二十号就要提…