做小米的笔试题,给出一个整数n,求出它在杨辉三角形中第一次出现的行号。

想了半天,只能暴力法,从第1行开始找,一直找到第n行,若找得到则返回行号,若找不到则返回n+1(因为第n+1行第2列肯定是n)。当然,注意1是在第1行而不是第2行。更好的方法倒是没想到,倒是折腾出了打印杨辉三角形前n行的最优方法。

如果空间不限制的话,就直接定义二维数组a[n][n],初始时a[0][0]=1,通过a[i][j]=a[i-1][j]+a[i-1][j-1]计算即可。这里主要注意的就是边界条件,每一行首尾必须为1,只有夹在首尾中间的n-2个元素才适用于这个公式。

不过后来发现,只是打印的话,完全可以用2个一维数组来表示前一行和当前行。用vector表示的话就是v1和v2,每次通过v1计算出v2,打印完v2之后迭代(用v2给v1赋值)。后来发现除了vector可能重新分配的问题(这里可以vector初始化大小为n来解决),用v2给v1赋值还是很没必要的。

于是想到了可以直接交换指针,v1和v2分配足够大空间后就一直不改变大小,然后int* p1 = &v1[0]; int* p2 = &v2[0];然后每次迭代只需要std::swap(p1,p2)即可。

这里相当于就是用了2片缓冲区(固定大小),其实知道行数上限的话,用2个数组表示也一样。

最后发现,缓冲区一片就够了,这里和copy/copy_backward的原理是类似的,只要从后往前遍历的话就不会导致新元素覆盖了旧元素从而计算出错。

然后更进一步,杨辉三角形每一行是对称的。于是我们只需要取前半部分即可,对于奇数行取(n+1)/2个,对于偶数行取n/2个,按照C/C++中除法取整来看都是(n+1)/2个。

关键是,第2k+1行和第2k+2行的前半部分元素数量相同(比如第3行是1,2,第4行是1,3),而第2k+3行最后一个元素无法直接计算。其实仔细看看就会发现规律,由于对称性,第2k+3行最后一个元素是第2k+2行最后一个元素的2倍。

到这里就可以写代码了,但是写代码的时候直接按这个思路来代码会很丑,因为奇数行最后一个元素的计算方式和前面元素的计算方式不一致。一个优雅的写法是,每当从偶数行跳到奇数行时,元素数量增加,并且初始时在末尾添加一个元素,再批量计算。

比如第4行是1 3,那么第5行初始化后就是1 3 3。然后a[2] = a[1] + a[0]; a[1] = a[1] + a[0];来计算。

// 打印杨辉三角形的前n行
void printPascalTriangle(int n)
{
int maxrow = (n + ) / ;
vector<int> v(maxrow + );
v[] = ; // 哨兵节点
bool bOddRow = true; // 奇数行则为true
int num = ; // 需要计算的元素数量
for (int row = ; row <= n; row++)
{
if (bOddRow)
{
num++;
v[num] = v[num - ];
}
for (int i = num; i > ; i--)
v[i] += v[i - ]; for (int i = ; i <= num; i++) // 正向打印
cout << v[i] << " ";
if (!bOddRow) // 对于偶数行最后一个元素需要再打印一遍
cout << v[num] << " ";
for (int i = num - ; i >= ; i--) // 反向打印
cout << v[i] << " ";
cout << endl;
bOddRow = bOddRow ? false : true; // 行号+1后改变了奇偶性
}
}

O(n)空间复杂度,打印杨辉三角形的前n行的更多相关文章

  1. 算法-利用队列实现逐行打印杨辉三角形的前n行

    分别打印二项式(a+b)^n展开项的系数,在程序中利用了一个队列,在输出上一行系数时,将下一行的系数预先放入队列中.在各行系数间插入0. void YANGVI(int n){ Queue q(n+) ...

  2. ACM解题之快速输出杨辉三角形(前68行)

    题意: 本题要求计算并输出杨辉三角形的前 68 行. Time Limit:1000MS Memory Limit:65536K 解题: 为了能在规定时间准确输出杨辉三角形的前68行,这里我用了精准的 ...

  3. 17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。 (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和。) 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1

    17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行.请采用循环控制语句来实现. (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和.) 1 1 1 1 ...

  4. 从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。

    Scanner sc=new Scanner(System.in); System.out.println("请输入一个正整数:"); int ss=sc.nextInt(); i ...

  5. grep命令打印前N行

    想打印前5行,用head即可:grep xxx |head -n 5

  6. linux利用grep查看打印匹配的下几行或前后几行的命令

    转自:http://www.itokit.com/2013/0308/74883.html linux系统中,利用grep打印匹配的上下几行   如果在只是想匹配模式的上下几行,grep可以实现.   ...

  7. spark dataframe操作集锦(提取前几行,合并,入库等)

    https://blog.csdn.net/sparkexpert/article/details/51042970 spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当 ...

  8. linux grep打印匹配的上下几行

    $grep -5 'parttern' inputfile //打印匹配行的前后5行 $grep -C 5 'parttern' inputfile //打印匹配行的前后5行 $grep -A 5 ' ...

  9. 1233: 输出杨辉三角前n行(Java)

    WUSTOJ 1233: 输出杨辉三角前n行 题目 原题链接 Description 输出杨辉三角前n行. Input 输入一个数n(n <= 9) Output 输出杨辉三角前n行.(注意行末 ...

随机推荐

  1. POJ 1008 简单模拟题

    e.... 虽然这是一道灰常简单的模拟题.但是米做的时候没有读懂第二个日历的计时方法.然后捏.敲完之后华丽的WA了进一个点.坑点就在一年的最后一天你是该输出本年的.e ...但是我好想并没有..看di ...

  2. oracleXE默认的管理员登录用户

    管理员: account:sys@XE as sysdba     pwd:sys sys@XE as sysdba             system

  3. Maven Spring BOM (bill of materials)

    为了防止用Maven管理Spring项目时,不同的项目依赖了不同版本的Spring,可以使用Maven BOM来解决者一问题. 在依赖管理时,引入spring-framework-bom,如: < ...

  4. apache2.4搭建php5.53问题总结

    1.如果Apache handler方式配置php,则最好选择Thread Safe,否则找不到php5apache2_4.dll.如果选择VC6版本以上的php,请到这里http://www.apa ...

  5. AngularJS-----$compile

    原文:http://docs.ngnice.com/api/ng/service/$compile 写在前面的话: 之前我一直理解错误,我一直以为这句--function([scope], clone ...

  6. Java内存不足之PermGen space错误探究

    一.Java 程序的运行机制与普通程序,如C或C++ 程序的运行机制有很大的区别. 普通程序运行之前必须首先编译成可执行的二进制码或机器码.机器码是与底层的硬件结构相关的,即使书写源代码的时候没有利用 ...

  7. TV-B-Gone Kit - Universal v1.2

  8. happypack 进一步 优化 build速率

    1.webpack.base.conf.js 使用happypack的正确姿势: 'use strict' const path = require('path') const utils = req ...

  9. 9.1 UDP协议

    TCP 协议是面向连接的基于流的,可靠的传输服务.UDP是无连接的,基于数据报的,不可靠的传输服务,UDP没有粘包,但是会产生丢包. UDP模型如下: 可以看到,服务器端不用listen,也不用acc ...

  10. matlab reshape()、full()

    一.reshape() 对于这个函数,就是重构矩阵. (1)要求:重构前后的矩阵元素个数一致.如3*4矩阵可以重构成2*6,2*3*2等. (2)重构方法:先按列将矩阵转换为向量,然后在向量的基础之上 ...