求第n个数的值

来源:互联网 发布:淘宝丫头正品商城正吗 编辑:程序博客网 时间:2024/06/04 17:58

第一题是网易互联网2015年的c/c++后台开发的编程题,题目的title似乎叫股神,大意可以简化为以下:

 

股票买进的价格为1,以后的第一天价格不变,第二天涨一天,第三天跌一天,接着涨两天,跌一天,张三天,跌一天。。。为方便起见,设每天增量或减量均为1,求第n天股票的价格?


解题思路:本题可以用传统的程序员思维解题,即从第一天开始计数,并用一个变量用来控制涨的循环次数,逐步累加,直到n天。此算法的复杂度为O(N),并无出彩地方,此处提供一种数学方法,可以讲算法复杂度将为O(1)


将涨跌看做一个整体,算出第n次涨跌后的总天数sum(n)

sum(0) = 1;

sum(1) = 1+1+1;

sum(2) = 1+1+2+2;

sum(3) = 1+1+2+3+3;

........

sum(n) = 1+1+2+3+..n+n = 1+(1+n)*n/2+n  这是sum的通项

对此可以列出不等式


n为正整数,对x取整,可以得到第n天之前涨跌的次数x;这时n-sum(x)必定处于涨潮之内(想想为什么?)此时,可以求得第n天的股价为

n-sum(x)+sum(x)-2*x = n-2*x;

代码如下:

#include <iostream>#include <cmath>using namespace std;//this is the version without using sqrt function to find iint find_index(const int &n){int i=1,sum=0;for(;i<=n;i++){sum += i;sum++;if(sum > n)    break;}return i-1;}int main(){int n;while(cin >>n){//int k = find_index(n-1);        int k = (-3+sqrt(1+8*n))/2;cout <<n-2*k <<endl;}return 0;}

第二题是indeed公司的某道笔试题,题目大致意思如下:

对于平面坐标系上的所有整数坐标,规定每个坐标点的大小如下:

点A(xA,yB)and  B(xB,yB)

若|xA|+|yA| >|xB|+|yB| 则点A大于点B,若绝对值之和相等,则比较x坐标的绝对值,若仍然相等,则比较x的大小,具有较大x值得点较小(譬如点(1,5)小于(-1,5),因为前一个坐标的x轴数值较大);再相等的话比较y的大小,具有较大y值的点较小;

将平面上所有点按从小到大排序,求出第n个点


此题的解题思路与上述题目一致,即先定义点的长度为坐标点绝对值之和,先求出第n个点的长度,接着求出改点在该长度中的位置。譬如

长度为1的点有(1,0),(-1,0),(0,1),(0,-1)

长度为2的点有(2,0)(-2,0)(1,1)(1,-1)(-1,1)(-1,-1)(0,2)(0,-2)

。。。

对于长度为n的点,其个数a,不难写出其通项公式:

a(0) = 1;
a(1) = 4;
a(2) = 8;

a(i) = 4*i;   // i 大于等于1

其前n项和为sum(n)


先求出第n个点的长度


如果remain为0,则第n个点就是(0,-i),否则,第n个点的长度为1+i,再根据remain的大小找出在长度为i+1的点中找出其第remain个点,即是所求点

以下是参考代码,若有bug,欢迎各位同行校正指出

代码提供了两个版本,一个是利用累加的方法求得i,另一个是利用数学计算;

#include <iostream>#include <cmath>using namespace std;//initial value of sum is 1 which correspond to (0,0)int find_index(const int &n,int &sum){int i=0;while(1){int a = 4*i;sum += a;if(sum > n){sum -= a;break;}i++;}return i;}//the value of x is greater or equal to 1int find_index(const int &n){int x = (sqrt(2*n-1)-1)/2+1;return x;}int find_position(int &remain,int &x){int y = 0;if(!remain){     //on the boundaryy = 1-x;x = 0;return y;}if(x ==1){        //the length is 1if(remain == 2)    x = -1;else if(remain == 3){x = 0;y =1;}}else if (remain == 2)   //the length is greater than 1    x = -x;else if(remain > 2){int i = (remain - 2)/4+1;remain -= 2+4*(i-1);    switch (remain){    case 0:{    x = i-x-1;    y = 1-i;         break;    }            case 1:{            x = x-i;            y = i;            break;            }    case 2:{    x = x-i;    y = -i;    break;    }    case 3:{    x = i-x;    y = i;    break;    }}}    return y;}int main(){int n=0;while(n++ <30){int x,sum,y,remain;x = find_index(n);sum = 1+2*x*(x-1);remain = n-sum;         y = find_position(remain,x);cout <<'(' <<x <<',' <<y <<')' <<endl;}cout <<"teset end!"   <<endl;return 0;}



0 0