• leetcode每日刷题


    🚀每日鸡汤:

                    从现在开始,不留余力地努力吧,最差的结果,也不过是大器晚成。

    🏆一、零矩阵

    来源:leetcode每日一题:零矩阵

    编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。

    👓①存坐标求解

    这道题比较简单的解法就是我们把这个二维数组遍历一遍,然后对于等于0的我们创建一个临时二维数组存储它的横纵坐标。这样,我们再通过临时二维数组就能找到所有为0的数,再把它所在的行和列的数置为0就解决了。

    时间复杂度:0(M*N)

    空间复杂度:0(M*N)

    1. void setZeroes(int** matrix, int matrixSize, int* matrixColSize)
    2. {
    3. int ret[matrixSize*(*matrixColSize)][2];
    4. int count=0;
    5. for(int i=0;i
    6. {
    7. for(int j=0;j<*matrixColSize;++j)
    8. {
    9. if(matrix[i][j]==0)
    10. {
    11. ret[count][0]=i;
    12. ret[count][1]=j;
    13. count++;
    14. }
    15. }
    16. }
    17. for(int i=0;i
    18. {
    19. for(int j=0;j<*matrixColSize;++j)
    20. {
    21. matrix[ret[i][0]][j]=0;
    22. }
    23. for(int m=0;m
    24. {
    25. matrix[m][ret[i][1]]=0;
    26. }
    27. }
    28. }

    👓②标记求解

    这道题目的优化就是能否降低它的空间复杂度呢?

    1、具体思路:

    我们采取标记的方式,二次遍历。第一次遍历,用一个变量flag(初始为false)来表示第一列是否有0,如果那一行的第一个数为0,就将flag置为true如果数组中哪个数据为0,就把这一列的第一个数和这一行的第一个数置为0.

    第二次遍历:我们倒着遍历对于第一列不遍历,对于每个数执行这样的判断:如果这个数所在的这一行第一个数为0或者它所在的这一列第一个数为0就把它置为0,然后对于不遍历的第一列,由于我们在第一次遍历时标记它是否有0,如果flag为true就置这一行第一个数为0。

    1. void setZeroes(int** matrix, int matrixSize, int* matrixColSize)
    2. {
    3. int m=matrixSize;
    4. int n=*matrixColSize;
    5. int flag=false;
    6. for(int i=0;i
    7. {
    8. if(!matrix[i][0])
    9. flag=true;
    10. for(int j=1;j
    11. {
    12. if(!matrix[i][j])
    13. {
    14. matrix[i][0]=matrix[0][j]=0;//这是在做标记
    15. }
    16. }
    17. }
    18. //倒着
    19. for(int i=m-1;i>=0;--i)
    20. {
    21. for(int j=1;j
    22. {
    23. if(!matrix[i][0]||!matrix[0][j])
    24. {
    25. matrix[i][j]=0;
    26. }
    27. }
    28. if(flag)
    29. {
    30. matrix[i][0]=0;
    31. }
    32. }
    33. }

    解释一下上述操作:

    1、flag变量用于标记第一列是否有0,有0的话这一列最后肯定要全置为0;

    2、对于《如果数组中哪个数据为0,就把这一列的第一个数和这一行的第一个数置为0》这一操作,也是一种标记功能,因为哪个数据为0它所在的行和列必须全为0,方便我们第二次遍历查看。

    3、第二次遍历要倒着遍历,正着遍历会对后续判断造成误导。

    🏆二、剪绳子

    来源:leetcode:剑指offer 剪绳子

    给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

     👓①动态规划

    刚拿道这道题目是比较头疼的,因为一段长度为n的绳子,我们要把它分成几段,要这几段加起来等于n,还要它们乘起来乘积最大,这个问题确实比较麻烦。但是凡事都是正难则反,我们能不能把复杂的问题转换成我们熟悉的简单的问题呢?我们来思考一些问题,计算几个数的乘积最大,是比较麻烦的,比较简单的是计算两个数的乘积最大,那么我们能不能把这个问题转化成计算两个数的乘积呢?

    有的老铁可能困惑,我两个数的乘积就能保证最大吗?这里就要再分化一下,如果它的两个数分别也是由两个数加和,然后乘积最大,如此递归下去,就递归到了一个数他恰好是分成两个数乘积最大!!!

    这道题我们再来分析一下:

     这是比较特殊的几种情况,到了长度为4,情况就变得复杂了,但是他也是两个数相乘时最大(2*2).所以从4开始,我们要把它们的最大乘积存储到一个数组中,到了5还是从数组中取两个数看哪一对乘积最大,再存储到数组里,这样就能得出每个长度分成若干长度的最大乘积

    时间复杂度:O(n^2)

    空间复杂度:O(n)

    1. int cuttingRope(int n)
    2. {
    3. //绳子最短要可以分成两段
    4. if(n<2)
    5. return 0;
    6. if(n==2)
    7. return 1;
    8. if(n==3)
    9. return 2;
    10. int *TemStore=(int*)malloc(sizeof(int)*(n+1));
    11. if(TemStore==NULL)
    12. {
    13. perror("malloc fail");
    14. exit(-1);
    15. }
    16. //对数组进行初始化
    17. TemStore[0]=0;
    18. TemStore[1]=1;
    19. TemStore[2]=2;
    20. TemStore[3]=3;
    21. //为什么初始化这几个,因为最短绳子从长度为4开始
    22. int max_length=0;
    23. for(int i=4;i<=n;++i)
    24. {
    25. max_length=0;
    26. for(int j=1;j<=i/2;++j)//超过一般就要重复了
    27. {
    28. int tmp=TemStore[j]*TemStore[i-j];
    29. if(tmp>max_length)
    30. max_length=tmp;
    31. TemStore[i]=max_length;
    32. }
    33. }
    34. return TemStore[n];
    35. }

    👓②贪婪算法

    如果我们按照这样的方式来剪绳子,则各段绳子的长度的乘积将最大;当n>=5时,我们要仅可能多地剪长度为3的绳子,当剩下的绳子长度为4时,把绳子剪成两段长度为2的绳子。

    问题:

    为什么尽可能多地去剪长度为3的绳子呢?这背后的数学理论比较复杂,简单来说:任何大于1的数都可以由2或3来组成,既然要求乘积最大,那么自然是3越多越好,所以要尽可能多地剪去3,但是当剩下绳子长度为4时,简称两端长度为2的绳子显然乘积更大。

    1. int cuttingRope(int n)
    2. {
    3. if(n<2)
    4. return 0;
    5. if(n==2)
    6. return 1;
    7. if(n==3)
    8. return 2;
    9. //特殊处理后
    10. int timesOf3=n/3;//有timesOf3段长度为3的绳子
    11. if(n-timesOf3*3==1)//说明剩余了4根绳子,但是由于我们除以3不能余4,只能是1
    12. timesOf3-=1;
    13. int timesOf2=(n-timesOf3*3)/2;//2段长度为2的绳子
    14. return (int)pow(3,timesOf3)*(int)pow(2,timesOf2);
    15. }

    时间复杂度:O(1)

    空间复杂度:O(1)

  • 相关阅读:
    亚马逊云科技通过生成式AI,帮助清华RIOS加速计算和分析的处理效率
    ubuntu 18.04安装教程(详细有效)
    led灯什么牌子的质量好?2022双十二家用护眼台灯推荐
    初始vue3
    Linux的关机和重启
    不讲故事的设计模式-责任链模式
    golang从0到1实战系统四十:处理表单的输入
    docker系列(7) - Dockerfile
    洞察运营机会的数据分析利器
    vlc将本地文件推流成ts实时流
  • 原文地址:https://blog.csdn.net/JJR_YZ/article/details/127124965