【左程云算法全讲10】打表技巧和矩阵处理技巧

系列综述:
目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
来源:材料主要源于左程云算法课程进行的,每个知识点的修正和深入主要参考各平台大佬的文章,其中也可能含有少量的个人实验自证。
结语:如果有帮到你的地方,就点个赞关注一下呗,谢谢!!!
【C++】秋招&实习面经汇总篇


文章目录

      • 打表法
      • 矩阵处理
    • 参考博客


点此到文末惊喜↩︎

打表法

  1. 打表

    • 作用:如果程序的值具有固定可接受的范围,可以通过计算每个值对应解,并形成一张表。从而提高计算速度
    • 方法:通过暴力方法打印尽可能多组映射示例,然后针对这多组映射示例推导规律,定制简单的算法
    • 方向
      • 笔试打表:可以直接通过5个左右的示例进行纸上暴力手动打表,找不出来再代码打表
      • 面试/工作:向面试官讲明原理,然后表示自己会进行完整的测试
    • 特点:
      • 输入参数类型简单,并且只有一个实际参数
      • 返回值类型简单,并且只有一个
      • 通过暴力方法将输入与返回值的对应关系打印出来,并优化
    • 步骤:
      • 编写简单的暴力方法,并打印多组示例的对应关系
      • 针对该多组示例的对应关系进行规律的查找,然后面向规律编程
  2. 打表法示例1

    • 小虎去买苹果,商店只提供两种类型的塑料袋,每种类型都有任意数量。
      • 1)能装下6个苹果的袋子
      • 2)能装下8个苹果的袋子
    • 小虎可以自由使用两种袋子来装苹果,但是小虎有强迫症,他要求自己使用的袋子数量必须最少,且使用的每个袋子必须装满。
    • 给定一个正整数N,返回至少使用多少袋子。如果N无法让使用的每个袋子必须装满,否则返回-1
      【左程云算法全讲10】打表技巧和矩阵处理技巧_第1张图片
  3. 打表法示例2

    • 定义一种数:可以表示成若干(数量>1)连续正数和的数,比如:
      • 5= 2+3, 5就是这样的数
      • 12 = 3+4+5, 12就是这样的数
      • 1不是这样的数,因为要求数量大于1个、连续正数和
      • 2= 1 + 1,2也不是,因为等号右边不是连续正数
    • 给定一个参数N,返回是不是可以表示成若干连续正数和的数
      【左程云算法全讲10】打表技巧和矩阵处理技巧_第2张图片
    • 判断num是不是2的某次方
      • (num & (num - 1)) == 0是2的某次方
      • (num & (num - 1)) !=0不是2的某次方

矩阵处理

  1. 矩阵特殊轨迹问题
    • 宏观调度法:
  2. 示例1:zigzag打印矩阵
    • 将打印轨迹进行分解:实际是每次打印一条A点和B点之间的斜线
      【左程云算法全讲10】打表技巧和矩阵处理技巧_第3张图片
void printMatrixZigZag(vector<vector<int>> matrix) {
  // 打印斜线
  auto print_bias = [&matrix](int Ar, int Ac, int Br, int Bc, bool direction) {
    if(direction) {
			while(Ar!=Br+1) {
				cout << matrix[Ar++][Ac--] << " ";
			}
		}else {
			while(Br!=Ar-1) {
				cout << matrix[Br--][Bc++] << " ";
			}
		}
  };

  // 主函数部分
  int Ar = 0;// A点和B点的坐标
  int Ac = 0;
  int Br = 0;
  int Bc = 0;
  int endR = matrix.size()-1;   // 边界
  int endC = matrix[0].size()-1;
  bool fromUp = false;
  while(Ar != endR+1) { // 结束条件:A的行坐标为下边界值+1
    print_bias(Ar,Ac,Br,Bc,fromUp);
    Ar = Ac==endC?Ar+1:Ar;  // A点到最后一列时,Ar开始下移
    Ac = Ac==endC?Ac:Ac+1;  // A点没到最后一列时,Ac右移
    Bc = Br==endR?Bc+1:Bc;  
    Br = Br==endR?Br:Br+1;
    fromUp = !fromUp;       // 方向交叉
  }
}
  1. 示例2:转圈打印矩阵
    • 子过程:每次顺时针打印一圈,
template<typename T>
void pirntEdage(std::vector<std::vector<T>>& my_matrix, int tR, int tC, int dR, int dC) {
    if (tR == dR) { 		// 行相同
        for (int i = tC; i <= dC; ++i) {
            std::cout << my_matrix[tR][i] << ",";
        }
    } else if (tC == dC) {  // 列相同
        for (int i = tR; i <= dR; ++i) {
            std::cout << my_matrix[i][tC] << ",";
        }
    } else {    			// 打印四条边
        int curR = tR;
        int curC = tC;
        while (curC != dC) {
            std::cout << my_matrix[tR][curC] << ",";
            ++curC;
        }
        while (curR != dR) {
            std::cout << my_matrix[curR][dC] << ",";
            ++curR;
        }
        while (curC != tC) {
            std::cout << my_matrix[dR][curC] << ",";
            --curC;
        }
        while (curR != tR) {
            std::cout << my_matrix[curR][tC] << ",";
            --curR;
        }
    }
}

template<typename T>
void spiralOrderPrint(std::vector<std::vector<T>>& my_matrix) {
    int tR = 0;
    int tC = 0;
    int dR = my_matrix.size() - 1;
    int dC = my_matrix[0].size() - 1;
    while (tR <= dR && tC <= dC) {
        pirntEdage(my_matrix, tR++, tC++, dR--, dC--);
    }
}
  1. 示例2:原地旋转正方形矩阵
    • 子过程:每次旋转一层
void Rotate(vector<vector<int>> matrix) {
	// 旋转一圈
	auto rotate_edge = [&matrix](int a, int b, int c, int d){
		int tmp = 0;
		// 每一圈一共执行d-b次
		// 每次顺时针交互对应的四个元素
		for (int i = 0; i < d-b; ++i) {
			tmp = matrix[a][b+i];
			matrix[a][b+i] = matrix[c-i][b];
			matrix[c-i][b] = matrix[c][d-i];
			matrix[c][d-i] = matrix[a+i][d];
			matrix[a+i][d] = tmp;
		} 
	};

	// 主逻辑
	int a = 0;
	int b = 0;
	int c = matrix.size()-1;
	int d = matrix[0].size()-1;
	while (a < c) {
		rotate_edge(matrix, ++a, ++b, --c, --d);
	}
}


少年,我观你骨骼清奇,颖悟绝伦,必成人中龙凤。
不如点赞·收藏·关注一波

点此跳转到首行↩︎

参考博客

  1. 转圈打印矩阵
  2. 待定引用
  3. 待定引用
  4. 待定引用

你可能感兴趣的:(左程云算法,算法,矩阵)