出题: 输入一个数字矩阵,要求从外向里顺时针打印每一个数字;
分析:
- 从外向里打印矩阵有多重方法实现,但最重要的是构建合适的状态机,这样才能控制多重不同的操作;
- 注意有四种打印模式(左右,上下,右左,下上),所以需要一个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 }