常见的基础算法以及技巧框架

简介: 常见的基础算法以及技巧框架

 image.gif编辑

👨‍💻个人主页:@元宇宙-秩沅

hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

本文由 秩沅 原创

收录于专栏 C++

目录

一,vector 容器于翻转字符串上的应用

二,字符反转

三,模拟

四,递归题框架

五,迷宫问题

六,stl的map,int>

七,Vector容器/动态数组( vector < int > a )

一,vector 容器于翻转字符串上的应用

#include<bits/stdc++.h>
#include<algorithm>
#include<vector>
using namespace std;
int flag;
int main ()
{
    string a , b ;
    int la , lb ;
    char temp ;
    int place;
    vector< char > w ;
    getline ( cin , a) ;
    la = a.length() ;
    b = a ;
    sort( b.begin() , b.end() ) ;
    temp = b[ 0 ] ;
    for ( int i = 0 ; i <= la - 1 ; i++ )
    {
        w.insert( w.end() , a[ i ] ) ;
    }
    while ( w[ w.size() - 1 ] == '0' &&  isdigit(w[ w.size() - 2] ) )
    {
        w.erase( w.end() - 1 ) ; //w.end()需要-1才能到动态数组中最后一个有效的数字 
    }
    if ( !isdigit(temp) )
    {
        place =  a. find( temp )  ; //返回下标 
        //cout << place ;
        reverse( w.begin( ) , w.begin() + place ) ;
        reverse( w.begin( ) + place + 1 , w.end() ) ;
        int i = 0 ,j = place + 1 ;
        while (  i < place  )
        {
            //cout << " w[i]=="<<w[ 0 ] <<endl ;
            if( w[ 0 ] == '0' && i + 1 != place  )  w.erase( w. begin( ) ) ;
            i++ ;
        }
        while (  j < la - 1  )  // la -1 为原来数组的最大下标 ,此时用来做最大执行次数 
        {
            if( w[ w.size() - 1] == '0' && j != la - 1) w.erase( w.end() - 1) ;
            j++ ;
        }
        for ( int i =0 ; i < w.size() ; i++ )
            cout << w[i] ;
    }
    else 
    {
        reverse( w.begin() , w.end() ) ;
        for ( int i =0 ; i < w.size() ; i++ )
            cout << w[i] ;
    }
    return 0;
}

image.gif

二,字符反转

1.sort( ) ;

(1)是c++时(string a)

sort( a . bedin () , a . end() ) ;

reverse ( a . bedin () , a . end() ) ;

find ( x ) ; //x为字符型 ,返回的则是它的位置

(2)是c时( char a[ ] )

sort( a , a + num ) ; // num为整型数字

reverse ( a , a + num ) ;

P1553 数字反转(升级版)链接

三,模拟

步骤

1.最优化解题,滤清大概思路解题 ,写出解题框架。

2.可考虑多开数组,用来巧妙避免小出错。

3.发生周期性变化时,可用“%”使得周期性能够简易表达。

4.为防止数组越界问题 ,下标得开大一点 。

5.下标从(1 . 1 )开始 比从 (0.0)开始要容易避免数组越界的问题 ,并且在第一行,第一列可当作数组的边界 ,以防数组越界问题的出现。

P1002 [NOIP2002 普及组] 过河卒链接

    1. 当遇到矩阵旋转时,核心是抓住n*n阶旋转矩阵的中间点,然后其他与其相邻的点都可以用它来表示(用两个循环框架),令一个关键 就是第一行到中心点的距离 r ,r= n(阶)/ 2 取整 ; r 直接影响 i 和 j ;

    P4924 [1007]魔法少女小Scarlet

    四,递归题框架

    步骤

    1.首先滤清题意 ,着重弄清要要解决什么问题

    2.判断要回溯 或 不用 ,若解题要回溯的话 ,也是根据函数返回的东西来判断,回溯的话函数就是空类型,方便回溯,一般 语句为 return ;

    3.条件的考虑:

    (1)结束条件是什么 ,有几个,在函数题的前端,回溯或递归是先行 运作。

    (2)要回溯时 ,回溯的条件是什么,

    (3)递归条件,有几个,什么时候需要递归,

    4,大局观 ,分析题目的大局,小问题后解决,框架先写出,时间顺序,先列大局,后小递归。

    P1028 [NOIP2001 普及组] 数的计算

    P1010 [NOIP1998 普及组] 幂次方P

    5.递归用到的小技巧,记忆化搜索 ,作用: 加快递归效率,减少运作时间,避免重复递归

    记忆化搜索

    1.设置数组来标记,递归时判断,递归第一次时则标记为已递归的标志

    2.设置数组直接存储递归的 值,借它的下标组作为访问它的标志,下此运转时,直接输出数组里面的值 ,

    该步骤比第一步更为简便 和实用 ,根据具体题目来分析

    P144 链接Function

    #include<iostream>
    #include<string>
    #include<climits>
    using namespace std;
    long long  p[22][22][22];
    long long he(long long a, long long b, long long c)
    {
        if (a <= 0 || b <= 0 || c <= 0) { return 1; }
        else if (p[a][b][c] != 0) return p[a][b][c];//搜索的关键
        else if (a > 20 || b > 20 || c > 20)
        {
            return  he(20, 20, 20);
        }
        else if (a < b && b < c)
        {
            p[a][b][c]= he(a, b, c - 1) + he(a, b - 1, c - 1) - he(a, b - 1, c);
            return p[a][b][c];
        }
        else
        {
            p[a][b][c] = he(a - 1, b, c) + he(a - 1, b - 1, c) + he(a - 1, b, c - 1) - he(a - 1, b - 1, c - 1);
            return p[a][b][c];
        }
    }
    int main()
    {
        long long  a, b, c;
        while (cin >> a >> b >> c)
        {
            if (a != -1 || b != -1 || c != -1)
            {
                printf("w(%lld, %lld, %lld) = ", a, b, c);
                if (a > 20)a = 21;
                if (b > 20)b = 21;
                if (c > 20)c = 21;
               cout<<he(a, b, c)<<endl;
            }
            else exit(0);
        }
        return 0; 
    }

    image.gif

    五,迷宫问题

    步骤:

    1.dfs( )函数一般是 void 空类型,回溯!

    2.确定递归条件 ;

    3确定回溯条件 ;

    4.确定结束条件 , 越界,或者不合法情况 ;

    5.小技巧:数组问题,迷宫问题时,可以开设方向数组/小数组 ;

    void dfs (  ) 
    {
        if (到达终点状态) //结束条件
        {
            return ;//回溯的标志
        }
        if (越界或者不合法情况) return; //回溯
        for ( 扩展方式 )
        {
            if(扩展方式 合法时)
            {
                进行修改操作;// 根据题意添加标记,如标记已访问
                    dfs();
                (还原标记,回溯后需要执行的条件); // 是否需要根据题意 ,加上还原条件就是回溯法
            }
        } 
    }
    代码优化后
    开设方向数组 dx 和 dy
    {dx[ 4 ] = { 0, 1 , 0 , - 1 }
    {dx[ 3 ] = { 1 , 0 , - 1 , 0 }
    #include<iostream>
    using namespace std ;
    int m,n ,p,q,min = 99999999;//技巧:给最小值设置一个很大的值
    int a[100][100],v[100][100];//前者是地图,后者是访问数组
    int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};//技巧:开设方向数组
    void dfs(int x , int y ,int step ) 
    {
        if( x == p && y == q )
        {
            if( step < min ) min = step ; // 巧妙的将最短路径的步数一个一个比较并且存入min其中
            return ; //比min 大则回溯推出 
        }
        for ( int k = 0 ; k <= 3 ; k++ ) // k为四个可以走的方向 :上下左右
        {
            int tx , ty ;
            tx = x + dx[k] ; 
            ty = y + dy[k] ;  //直接利用方向数组,将往哪个方向走巧妙的表达出来
            if( a[ tx ][ ty ] == 1 && v[ tx ][ ty ] == 0 ) //表示此时是空地且未访问 
            {
            v[ tx ][ ty ] == 1 ;//将该点访问
              dfs ( tx , ty , step + 1 ) ; // 继续搜索
                v[ tx ][ ty ] == 0 ; //当有一步到达终点后,它需要回退也就是回溯 ,重新找不同
                                    //的路径,因为不排除其他三个方向都可以走的情况,也就是新路线
                                   //所以之前走过的地方需要重新标记为未访问 
            }
            return ;
        }
    }
    int main ()
    {
        int startx = 1  ,starty = 1; //定义起点的位置
        cin >> m >> n ;//地图大小
        cin >> p >> q ;//终点坐标
        for (int i = 1 ; i <= m ; i++ ) //画地图标明空地和障碍 空地为1,障碍为2
        {
            for (int j = 0 ; j <= n ; j++ )
                 cin  >> a[i][j] ;
        }
        v[startx][starty] = 1 ; //已访问标记
        dfs ( startx , starty , 0 ) ; //dfs 进行最短路径探索 , 0 是步数
        cout << min ;
    return 0 ;
    }

    image.gif

    未优化的递归回溯:

    image.gif编辑

    六,stl的map<char,int>

    #include<iostream>
    #include<map>
    #include<math.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    map<char,int>m;
    int main(){
        int maxx=-999999,minn=999999;
        char a[101];
        cin>>a;
        int l=strlen(a);
        for(int i=0;i<l;i++){
            m[a[i]]++;
            maxx=max(maxx,m[a[i]]);
            //minn=min(minn,m[a[i]]);
        }
        for(int i=0;i<l;i++){
            minn=min(minn,m[a[i]]);
        }
        //cout<<maxx<<' '<<minn<<endl;
        maxx-=minn;
       // cout<<maxx<<endl;
        if(maxx==0||maxx==1){
            cout<<"No Answer"<<endl;
                cout<<0;
                return 0;
        }
        for(int i=2;i<=sqrt(maxx);i++){
            if(maxx%i==0){
                cout<<"No Answer"<<endl;
                cout<<0;
                return 0;
            }
        }
        cout<<"Lucky Word"<<endl;
        cout<<maxx;
        return 0;
    }

    image.gif

    七,Vector容器/动态数组( vector < int > a )

    1,算法

    排序 :sort ( a. begin( ) , a. end( ) );

    反转 :reverse( a. begin( ) , a. end( ) );

    查询 :find ( a. begin( ) , a. end( ) , number ) ; 自推仅限整型

    2,函数

    返回第一个元素:a . front( ) ;

    判断容器空否:a . empty( ) ;

    删除: a . erase ( a . begin ( ) ) ;

    a . erase( a. end( ) - 1 ) ;

    插入: a . insert ( a.bigin( ) , x ) ;

    3,实例

    P1553 数字反转(升级版)链接

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int flag;
    int main ()
    {
      string a , b ;
      int la , lb ;
      char temp ;
      int place;
      vector< char > w ;
      getline ( cin , a) ;
      la = a.length() ;
      b = a ;
      sort( b.begin() , b.end() ) ;
      temp = b[ 0 ] ;
      for ( int i = 0 ; i <= la - 1 ; i++ )
      {
        w.insert( w.end() , a[ i ] ) ;
      }
      while ( w[ w.size() - 1 ] == '0' &&  isdigit(w[ w.size() - 2] ) )
      {
        w.erase( w.end() - 1 ) ; //w.end()需要-1才能到动态数组中最后一个有效的数字 
      }
      if ( !isdigit(temp) )
      {
      place =  a. find( temp )  ; //返回下标 
      //cout << place ;
      reverse( w.begin( ) , w.begin() + place ) ;
      reverse( w.begin( ) + place + 1 , w.end() ) ;
      int i = 0 ,j = place + 1 ;
        while (  i < place  )
        {
          //cout << " w[i]=="<<w[ 0 ] <<endl ;
          if( w[ 0 ] == '0' && i + 1 != place  )  w.erase( w. begin( ) ) ;
          i++ ;
      }
        while (  j < la - 1  )  // la -1 为原来数组的最大下标 ,此时用来做最大执行次数 
        {
          if( w[ w.size() - 1] == '0' && j != la - 1) w.erase( w.end() - 1) ;
          j++ ;
      }
      for ( int i =0 ; i < w.size() ; i++ )
      cout << w[i] ;
        }
        else 
        {
        reverse( w.begin() , w.end() ) ;
        for ( int i =0 ; i < w.size() ; i++ )
      cout << w[i] ;
      }
    return 0;
    }

    image.gif

    你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!

    栓Q  

    image.gif编辑


    目录
    相关文章
    |
    5月前
    |
    搜索推荐 前端开发 数据可视化
    【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
    本文介绍了一个基于Django框架、协同过滤算法、ECharts数据可视化以及Bootstrap前端技术的酒店推荐系统,该系统通过用户行为分析和推荐算法优化,提供个性化的酒店推荐和直观的数据展示,以提升用户体验。
    191 1
    【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
    |
    2月前
    |
    算法
    ”回溯算法“框架及练习题
    ”回溯算法“框架及练习题
    48 0
    |
    5月前
    |
    搜索推荐 前端开发 算法
    基于用户画像及协同过滤算法的音乐推荐系统,采用Django框架、bootstrap前端,MySQL数据库
    本文介绍了一个基于用户画像和协同过滤算法的音乐推荐系统,使用Django框架、Bootstrap前端和MySQL数据库构建,旨在为用户提供个性化的音乐推荐服务,提高推荐准确性和用户满意度。
    359 7
    基于用户画像及协同过滤算法的音乐推荐系统,采用Django框架、bootstrap前端,MySQL数据库
    |
    8月前
    |
    缓存 算法 安全
    Java集合框架:深入探究数据结构与算法的精华
    Java集合框架:深入探究数据结构与算法的精华
    |
    5月前
    |
    数据采集 前端开发 算法
    基于朴素贝叶斯算法的新闻类型预测,django框架开发,前端bootstrap,有爬虫有数据库
    本文介绍了一个基于Django框架和朴素贝叶斯算法开发的新闻类型预测系统,该系统具备用户登录注册、后台管理、数据展示、新闻分类分布分析、新闻数量排名和新闻标题预测等功能,旨在提高新闻处理效率和个性化推荐服务。
    |
    5月前
    |
    缓存 算法 关系型数据库
    BP-Wrapper:无锁竞争的替换算法系统框架
    BP-Wrapper:无锁竞争的替换算法系统框架
    63 2
    |
    5月前
    |
    测试技术 数据库
    探索JSF单元测试秘籍!如何让您的应用更稳固、更高效?揭秘成功背后的测试之道!
    【8月更文挑战第31天】在 JavaServer Faces(JSF)应用开发中,确保代码质量和可维护性至关重要。本文详细介绍了如何通过单元测试实现这一目标。首先,阐述了单元测试的重要性及其对应用稳定性的影响;其次,提出了提高 JSF 应用可测试性的设计建议,如避免直接访问外部资源和使用依赖注入;最后,通过一个具体的 `UserBean` 示例,展示了如何利用 JUnit 和 Mockito 框架编写有效的单元测试。通过这些方法,不仅能够确保代码质量,还能提高开发效率和降低维护成本。
    62 0
    |
    8月前
    |
    设计模式 算法 Java
    [设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
    [设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
    |
    8月前
    |
    机器学习/深度学习 人工智能 自然语言处理
    |
    8月前
    |
    算法 关系型数据库 API
    Python【算法中心 02】Web框架Django管理页面使用(管理员账号创建+API使用+应用添加)GreenPlum数据库引擎及API测试
    Python【算法中心 02】Web框架Django管理页面使用(管理员账号创建+API使用+应用添加)GreenPlum数据库引擎及API测试
    119 0

    热门文章

    最新文章