做小米的笔试题,给出一个整数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. 禁止一个click事件执行的方法

    用jquery点击一次之后,在里面给这个元素加上这个样式,就可以了. 'pointer-events':'none'

  2. React教程-组件

    在React中创建一个组件非常简单(React组件有2种,一个非状态组件,一个有状态组件) 首先我们来看看ES6里面如何写构造函数 class App{ constructor(){ } event( ...

  3. hdu 3072 Intelligence System(Tarjan 求连通块间最小值)

    Intelligence System Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) ...

  4. html <meta>设置自动刷新或者几秒内跳转到指定页面

    指定时间自动刷新: <meta http-equiv="refresh" content="2"/> 指定时间跳转到指定页面: <meta h ...

  5. Error:Cannot compile Groovy files: no Groovy library is defined for module 'xxxx' 错误处理

    出现 Error:Cannot compile Groovy files: no Groovy library is defined for module 'xxxx' 只要在 project str ...

  6. Installing MIB in Ubuntu and Solving the Error “SNMP Cannot Find Module …”

    Has noticed an error after executing the command snmpwalk with the indication of MIB instead of OID: ...

  7. firefox下reset()不好使的问题

    最近在测试项目时发现,在firefox下,form.reset()方法对于隐藏的<input>等不起效果,导致程序中出现了错误,以下面为例: js代码: document.agentFor ...

  8. 使用jenkins进行项目的自动构建部署

    jenkins 简介 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括:持续的软件版本发布/测试项目和监控外部调用执行的工作. 官网地址地址: https://je ...

  9. sed使用笔记

    1.在匹配行前后添加内容 i a sed -i -r '/Processrun.sh/a01 00 * * * /data/scripts/nginx/ngx_logcut.sh' /var/spoo ...

  10. ZooKeeper安装,部署

    实验环境 192.168.1.10 Zookeeper1:2181, Zookeeper2:2182 192.168.1.11 ZooKeeper3:2181 依赖环境 JDK1.7 安装,配置 1. ...