牛客网算法教程-中级篇-第一章

学习目标:

牛客网中级算法题 第一章

学习内容:

1.旋转词-模拟
2.旋转矩阵-模拟
3.数轴覆盖-贪心
4.1 完整字符串1(括号字符串的有效性)-栈
4.2 完整字符串2(缺失的括号)-栈
4.3 完整字符串3(最长合法括号子串)-栈
5.打包机器人-贪心
6.1容器装水-贪心
6.2地形盛水-贪心
7.牛牛找工作-有序表
8.安置路灯-贪心


学习时间:

2022.3.1-2022.3.6

学习产出:

1.旋转词-模拟

牛客网题目连接
如果一个字符串为str,把字符串的前面任意部分挪到后面形成的字符串叫str的旋转词。比如str=“12345”,str的旋转串有“12345”、“45123”等等。给定两个字符串,判断是否为旋转词。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
解析:
在这里插入图片描述

1.备注时间复杂度和空间复杂度为O(N),这就表示,我们不能用暴力法去求解了。
2.我们通过仔细阅读题目,不难发现,如果旋转词的长度和原来串的长度不一致,那么肯定是NO
3.我们使用的方法是,扩大串。将str= str + str
在这里插入图片描述
4.所以我们的算法的难度来到了KMP,这是一个经典的判断字串的算法

using System;

namespace test{
   
    class test{
   
        static void Main(string[] args){
   
            string lengthIn=Console.ReadLine();
            string[] lengthSplit=lengthIn.Split(' ');
            int length1=Convert.ToInt32(lengthSplit[0]);
            int length2=Convert.ToInt32(lengthSplit[1]);
				
            if(length1!=length2){
   
                Console.WriteLine("NO");
                return;
            }
                
            
            string l1=Console.ReadLine();
            string l2=Console.ReadLine();  //第二个字符串
            
            //让字符串扩大两倍
            string big=l1+l1;
            
            
            for(int i=0;i<big.Length;i++){
   
                if(big[i]==l2[0]){
   
                    if(IsChild(i,big,l2)){
   
                        Console.WriteLine("YES");
                        return;
                    }
                        
                }
            }
            Console.WriteLine("NO");
            
        }
        
        //KMP
        static bool IsChild(int begin,string father,string child){
   
            int childindex=0;
            for(int i=begin;i<father.Length;i++){
   
                if(father[i]!=child[childindex]){
   
                    return false;
                }
                childindex++;
                if(childindex>=child.Length)return true;
            }
            return true;
        }
    }
}

总结:这里我们采用基地址的方法,以每个基地址作为处理对象,通过将每个基地址的情况进行计算,得到最优的答案。
局部->最优

2.旋转矩阵-模拟

牛客网链接
有一个NxN整数矩阵,请编写一个算法,将矩阵顺时针旋转90度。

给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转后的NxN矩阵。
在这里插入图片描述
解析:
在这里插入图片描述

1.其实我们可以创新一个新的矩阵,然后将旧矩阵旋转之后,赋值给新矩阵,只需要找到对应点旋转后的关系即可。
2.但是,进阶要求是要我们去实现空间复杂度为O(1),意思就是不创建新的矩阵,就在原来的矩阵里面进行旋转
3.我们采取剥洋葱的方法,一层一层的去实现旋转。首先是最外面一层,我们的发现他们的规律,红色的组一,就是四个顶点,他们旋转的位置很容易发现规律。我们只需要用一个去覆盖另外一个即可。然后紧跟着的绿色组二,和组一位置的关系很紧密,看下面写的for循环就可以理解了。
4.for循环的一次循环,代表完成一组。比如i=0,执行完后,组1完成旋转。比如i=1,执行完成后,组2完成选择。所以,一个for循环,就可以解决一圈的数据
5.我们只需要让abcd的值,不断往里面缩。下一个圈,就是a+1,b+1,c-1,d-1
6.直到a>c了,就是都完成了
在这里插入图片描述

using System;
class Solution
{
      
    public int[][] rotateMatrix(int[][] mat, int n)
    {
   
        int a=0;
        int b=0;
        int c=n-1;
        int d=n-1;
        while(a<c){
   
            RotateOne(mat,a++,b++,c--,d--);
        }
        PrintMat(mat,n);
        return mat;
    }
    
    public static void RotateOne(int[][] mat,int a,int b,int c,int d){
   
        for(int i=0;i<d-b;i++){
   
            int temp=mat[a][b+i];
            mat[a][b+i]=mat[c-i][b];
            mat[c-i][b]=mat[c][d-i];
            mat[c][d-i]=mat[a+i][d];
            mat[a+i][d]=temp;
        }
    }
    
    
    public static void PrintMat(int[][] mat,int n){
   
        Console.Write('[');
        for(int i=0;i<n;i++){
   
            Console.Write('[');
            for(int j=0;j<n;j++){
   
                Console.Write(mat[i][j]);
                Console.Write(',');
            }
            Console.Write(']');
        }
        Console.Write(']');
    }
}

总结:
这道题我们应该舍弃局部,而是从整体来进行处理。以整体去推局部,如果纠结于某个局部的值怎么样去转换, 那会很难!
如果我们分析整体,发现客观规律,那我们就可以轻松应对。
将局部代入整体

3.数轴覆盖-贪心

牛客网链接
在这里插入图片描述
在这里插入图片描述
分析:
在这里插入图片描述

在这里插入图片描述
1.这里使用的是3方法,滑动窗口法。以Left作为窗口左边,Right作为窗口右边。Right试着往右边无限扩大窗口,直到无法扩大,即让Left往前移动一格。每一次右边无法扩大的时候,即是Left位置窗口的最大值。此时应该刷新Max。

using System;
namespace test{
   
    class test{
   
        static void Main(){
   
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值