zoukankan      html  css  js  c++  java
  • 笔试算法题(26):顺时针打印矩阵 & 求数组中数对差的最大值

    出题: 输入一个数字矩阵,要求从外向里顺时针打印每一个数字;

    分析:

    • 从外向里打印矩阵有多重方法实现,但最重要的是构建合适的状态机,这样才能控制多重不同的操作;
    • 注意有四种打印模式(左右,上下,右左,下上),所以需要一个index变量控制每次循环时执行的打印模式;
    • 注意水平打印和垂直打印分别需要两个变量控制打印元素,并且两组变量中的两个端点都是相互靠近的(hs和he,vs和he),每执行一种打印模式之前,需要更新当前打印模式中打印方向的其实坐标,因为它已经在上一种打印模式中打印过;
    • 每一种打印模式执行之前需要检测hs>he或者vs>ve,如果成立则打印结束;
    • 其他方法:递归法:每次都打印矩阵第一行,然后将剩余的元素逆时针旋转90度创建一个矩阵;贪吃蛇法:创建一个bool矩阵表示元素是否被打印,然后创建一个类似index的控制打印模式的变量,遇到false的元素就转到下一个打印模式;

    解题:

     1 /**
     2  * 设置四个变量,两两一组分别表示水平和垂直方向的打印的起始点
     3  * index表示四种打印方式中的一种(左右,上下,右左,下上)
     4  * 当两两一组的变量中hs>he或者vs>ve的时候结束打印
     5  * 注意每一种打印模式开始之前,需要更新起始点的坐标,因为
     6  * 它已经在上一个打印模式中打印过
     7  * */
     8 void clockwisePrintMatrix(int *array, int x, int y) {
     9         int hs=-1, he=x-1;
    10         int vs=0, ve=y-1;
    11         int index=4;
    12 
    13         while(true) {
    14                 printf("hs=%d, he=%d, vs=%d, ve=%d
    ",hs,he,vs,ve);
    15                 index%=4;
    16                 if(index==0) {
    17                         /**
    18                          * 左右打印模式:
    19                          *
    20                          * */
    21                         hs++;
    22                         if(hs>he) break;
    23                         for(int i=hs;i<=he;i++)
    24                                 printf("%d, ",array[vs*x + i]);
    25                         printf("
    ");
    26                 } else if(index==1) {
    27                         /**
    28                          * 上下打印模式:
    29                          *
    30                          * */
    31                         vs++;
    32                         if(vs>ve) break;
    33                         for(int i=vs;i<=ve;i++)
    34                                 printf("%d, ",array[i*y + he]);
    35                         printf("
    ");
    36                 } else if(index==2) {
    37                         /**
    38                          * 右左打印模式:
    39                          *
    40                          * */
    41                         he--;
    42                         if(hs>he) break;
    43                         for(int i=he;i>=hs;i--)
    44                                 printf("%d, ",array[ve*x + i]);
    45                         printf("
    ");
    46                 } else if(index==3) {
    47                         /**
    48                          * 下上打印模式:
    49                          *
    50                          * */
    51                         ve--;
    52                         if(vs>ve) break;
    53                         for(int i=ve;i>=vs;i--)
    54                                 printf("%d, ",array[i*y + hs]);
    55                         printf("
    ");
    56                 }
    57                 index++;
    58         }
    59 }
    60 
    61 int main() {
    62         int matrix[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25};
    63         clockwisePrintMatrix(matrix, 5, 5);
    64         return 0;
    65 }

    出题:一个数组中,某一个数字减去它右边数字得到一个数对差,求所有数对差中的最大值;

    分析:

    • 数对差的解法可转换成求最大子数组和,或者转换成DP问题;
    • 解法1:构建子数组最大和值
      定义数 组:array[i]-array[i+1];array[i+1]-array[i+2];……;array[j-1]-array[j];所以 array[i]-array[j]的差就是前面所有相邻元素差的和,所以将原始数组转换成相邻元素的差组成的数组,而求原数组元素差的最大值转换成新数 组的子数组元素的最大和;
    • 解法2:动态规划解法:diff[i]存储array[i]与其左边数组最大元素的差值,得到diff[i]之后求diff[i+1],则需要知道 array[i+1]左边数组的最大元素,而有两种可能,计算diff[i]的时候得到的最大值,或者就是array[i]。所以只需一遍扫描就可以;

    解题:

     1 int MaxDif(int *array, int length) {
     2         /**
     3          * 定义局部stack数组存储相邻元素差值
     4          * 循环获取相邻元素差值
     5          * */
     6         int difarray[length-1];
     7         for(int i=0;i<length-1;i++) {
     8                 difarray[i]=array[i]-array[i+1];
     9                 printf("
    %d",difarray[i]);
    10         }
    11         /**
    12          * sum记录最大和值
    13          * tempsum记录当前元素的和值
    14          * 如果元素为+++++++,则从开始相加到最后
    15          * 如果元素为-------,则sum保持为0
    16          * 如果元素为++++---,则sum保持为前半正数
    17          * 如果元素为----+++,则sum保持为后半正数
    18          * 还有其他满足条件的情况
    19          * */
    20         int tempsum=0, sum=0;
    21         for(int i=0;i<length-1;i++) {
    22                 tempsum+=difarray[i];
    23                 if(tempsum<0)
    24                         tempsum=0;
    25                 else if(tempsum>sum)
    26                         sum=tempsum;
    27         }
    28 
    29         return sum;
    30 }
    31 
    32 int MaxDifDP(int *array, int length) {
    33         /**
    34          * difarray[i]用于存储array[i]左边的最大元素
    35          * 与array[i]的差值,
    36          * difarray[i+1]同理,但根据DP原理,左边的最大
    37          * 元素可能是array[i]找到的最大元素,可能是
    38          * array[i]本身,所以一遍扫描,DP复用
    39          * */
    40         int difarray[length-1];
    41         int max=array[0];
    42         for(int i=0;i<length-1;i++) {
    43                 if(array[i]>max)
    44                         max=array[i];
    45                 difarray[i]=max-array[i+1];
    46         }
    47         int difmax=difarray[0];
    48         for(int i=1;i<length-1;i++) {
    49                 if(difarray[i]>difmax)
    50                         difmax=difarray[i];
    51         }
    52         return difmax;
    53 }
    54 
    55 int main() {
    56         int array[]={6,7,9,6,-4,0,7,9};
    57         printf("
    the max diff is: %d",MaxDif(array,8));
    58         printf("
    the max diff is: %d",MaxDifDP(array,8));
    59         return 0;
    60 }
  • 相关阅读:
    DEV GridControl打印 导出
    DES加密解密类
    多例模式,保证实例的唯一性,仅适用于form窗体
    c# 计算星座
    官方Radare2书之简介
    linux & windows手机 (长期更新)
    非kali官方源中的那些优秀软件们 --- java反编译反汇编器引擎汇总(长期更新)
    常见的那些模糊不清的计算机相关概念(长期更新)
    什么是网站追踪?它为什么要追踪我?
    浅谈生活中常见的三大应用程序架构(PE、ELF、Mach-O)、五大操作系统(windows、linux、macos、android、ios)和三大cpu架构(x86、arm、mips)
  • 原文地址:https://www.cnblogs.com/leo-chen-2014/p/3747108.html
Copyright © 2011-2022 走看看