第一题是网易互联网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 i
int 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 1
int 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 boundary
y = 1-x;
x = 0;
return y;
}
if(x ==1){ //the length is 1
if(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;
}