life02

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  197 随笔 :: 3 文章 :: 37 评论 :: 0 Trackbacks

#

题目转自:
http://blog.163.com/ecy_fu/blog/static/444512620098228849190/
 二笔只有三道题,分值分别为30, 30, 40,题分别如下:
1、实现strtol函数,其原型如为int strtol(const char *num_str, char **endptr, int base),num_str存放待转换的字符串,可以是负数也可以是正数;endptr指向第一个非法字符的地址,如果endptr为NULL则不指向第一个非法字符的地址;base用于指示进制,若base为0,则根据num_str的指示来转换。函数必须检查溢出,如果正数溢出,返回INT_MAX;若负数溢出,返回INT_MIN。
2、一亿个数找最大的1000个数,要求效率高占用内存少。函数原型为:find_max_data(int* source_data, int* max_data),其中source_data是存放一亿个数的数组,max_data用于存放其中最大的1000个数。
3、将一个集合拆分成两个不相交的子集,两个子集元素之和相等,如{1, 2, 3, 4, 5, 6, 7},拆分成:
{2, 5, 7}, {1, 3, 4, 6}
给出一个集合,求所有符合上面要求的拆分,效率最高分越高,函数原型为int cal_num(int n);

第三题:
利用回溯剪枝法
空间复杂度:O(n) 栈的最大深度也就是n了
时间复杂度:接近于O(2^n-1), 因为本质上程序时一个遍历树的过程,如果没有剪枝,那么树是一个满二叉树,结点共2^n-1个,也就要遍历2^n-1次。虽然剪枝,但速度估计仍是 2^n次方级别的。
试了下,调用cal_num(104),好久了结果都没有出来。。。

不知用上DP算法会不会好点,不过听说回溯法怎么弄效率都跟不上,最好用递推?
在哪听说的?
http://topic.csdn.net/u/20090922/11/ebc26b48-6581-40c3-afe0-a95ca2d700d5.html

 

/////////////////////////////////////////////////////////////////
//file divide_set.h:

#ifndef __DIVIDE_SET_H__
#define __DIVIDE_SET_H__

// 计算集合set的所有满足下列条件的子集合:子集合元素之和等于value
// 子集合的元素对应的label置1
void divide_set( int set[], int label[], int len, int i_set, int value );

// 对集合{1,2,n}划分
void cal_num( int n );

#endif


/////////////////////////////////////////////////////////////////
//file divide_set.cpp:

#include 
"stdafx.h"
#include 
"divide_set.h"

#include 
<iostream>

using namespace std;

// 查找集合set中,满足元素之和等于value的子集合,结果存于label里
void divide_set( int set[], int label[], int len, int i_set, int value )
{
 
// 输出结果
 if ( value == 0 )
 
{
  cout
<<"";
  
for ( int i=0; i<len; ++i )
  
{
   
if ( label[i] )
   
{
    cout
<<set[i]<<" ";
   }

   
  }

  cout
<<"";
  cout
<<" , { ";
  
for ( int i=0; i<len; ++i )
  
{
   
if ( 0 == label[i] )
   
{
    cout
<<set[i]<<" ";
   }

  }

  cout
<<"";
  cout
<<endl;
  
return;
 }


 
if ( i_set >= len || value <0)
 
{
  
return;
 }


 
// 取第i_set个元素
 label[i_set] = 1;
 divide_set( 
set, label, len, i_set+1, value-set[i_set] );
 
 
// 不取第i_set个元素
 label[i_set] = 0;
 divide_set( 
set, label, len, i_set+1, value );
}


void cal_num( int n )
{
 
int* set = new int[n];
 
int* label = new int[n];

 
// initialize set and label
 int sum_value = 0;
 
for ( int i=0; i<n; ++i )
 
{
  
set[i] = i+1;
  sum_value 
+= set[i]; 
 }

 memset( label, 
0, n*sizeof(int) );

 
// 保证元素总和为偶数
 if( sum_value%2 == 0 )
  divide_set( 
set, label, n, 0, sum_value/2 );

 delete[] 
set;
 delete[] label;
}


 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zdl1016/archive/2009/10/04/4632688.aspx

posted @ 2009-10-07 11:08 life02 阅读(513) | 评论 (1)编辑 收藏

面试过程中,面试官会向应聘者发问,而应聘者的回答将成为面试官考虑是否接受他的重要依据。对应聘者而言,了解这些问题背后的“猫腻”至关重要。本文对面试中经常出现的一些典型问题进行了整理,并给出相应的回答思路和参考答案。读者无需过分关注分析的细节,关键是要从这些分析中“悟”出面试的规律及回答问题的思维方式,达到“活学活用”。
 
  问题一:“请你自我介绍一下”
 
  思路: 1、这是面试的必考题目。 2、介绍内容要与个人简历相一致。 3、表述方式上尽量口语化。 4、要切中要害,不谈无关、无用的内容。 5、条理要清晰,层次要分明。6、事先最好以文字的形式写好背熟。
 
  问题二:“谈谈你的家庭情况”
 
  思路:1、 况对于了解应聘者的性格、观念、心态等有一定的作用,这是招聘单位问该问题的主要原因。 2、 简单地罗列家庭人口。 3、 宜强调温馨和睦的家庭氛围。 4、 宜强调父母对自己教育的重视。 5、 宜强调各位家庭成员的良好状况。 6、 宜强调家庭成员对自己工作的支持。 7、 宜强调自己对家庭的责任感。
 
    问题三:“你有什么业余爱好?”
 
  思路: 1、 业余爱好能在一定程度上反映应聘者的性格、观念、心态,这是招聘单位问该问题的主要原因。 2、 最好不要说自己没有业余爱好。 3、 不要说自己有那些庸俗的、令人感觉不好的爱好。 4、 最好不要说自己仅限于读书、听音乐、上网,否则可能令面试官怀疑应聘者性格孤僻。 5、 最好能有一些户外的业余爱好来“点缀”你的形象。
 
  问题四:“你最崇拜谁?”
 
  思路: 1、 最崇拜的人能在一定 程度上反映应聘者的性格、观念、心态,这是面试官问该问题的主要原因。 2、 不宜说自己谁都不崇拜。 3、 不宜说崇拜自己。 4、 不宜说崇拜一个虚幻的、或是不知名的人。 5、 不宜说崇拜一个明显具有负面形象的人。 6、 所崇拜的人人最好与自己所应聘的工作能“搭”上关系。 7、 最好说出自己所崇拜的人的哪些品质、哪些思想感染着自己、鼓舞着自己。
 
  问题五:“你的座右铭是什么?”
 
  思路: 1、座右铭能在一定程度上反映应聘者的性格、观念、心态,这是面试官问这个问题的主要原因。 2、不宜说那些医引起不好联想的座右铭。 3、不宜说那些太抽象的座右铭。 4、不宜说太长的座右铭。 5、座右铭最好能反映出自己某种优秀品质。 6、 参考答案——“只为成功找方法,不为失败找借口”。
 
  问题六:“谈谈你的缺点”
 
  思路: 1、 不宜说自己没缺点。 2、 不宜把那些明显的优点说成缺点。 3、 不宜说出严重影响所应聘工作的缺点。 4、 不宜说出令人不放心、不舒服的缺点。 5、 可以说出一些对于所应聘工作“无关紧要”的缺点,甚至是一些表面上看是缺点,从工作的角度看却是优点的缺点。
 
  问题七:“谈一谈你的一次失败经历”
 
  思路: 1、 不宜说自己没有失败的经历。 2、 不宜把那些明显的成功说成是失败。 3、 不宜说出严重影响所应聘工作的失败经历, 4、 所谈经历的结果应是失败的。 5、 宜说明失败之前自己曾信心白倍、尽心尽力。 6、 说明仅仅是由于外在客观原因导致失败。 7、 失败后自己很快振作起来,以更加饱满的热情面对以后的工作。

  问题八:“你为什么选择我们公司?”
 
  思路: 1、 面试官试图从中了解你求职的动机、愿望以及对此项工作的态度。 2、 建议从行业、企业和岗位这三个角度来回答。 3、 参考答案——“我十分看好贵公司所在的行业,我认为贵公司十分重视人才,而且这项工作很适合我,相信自己一定能做好。”

  问题九:“对这项工作,你有哪些可预见的困难?”
 
  思路: 1、 不宜直接说出具体的困难,否则可能令对方怀疑应聘者不行。 2、 可以尝试迂回战术,说出应聘者对困难所持有的态度——“工作中出现一些困难是正常的,也是难免的,但是只要有坚忍不拔的毅力、良好的合作精神以及事前周密而充分的准备,任何困难都是可以克服的。”

  问题十:“如果我录用你,你将怎样开展工作”
 
  思路: 1、 如果应聘者对于应聘的职位缺乏足够的了解,最好不要直接说出自己开展工作的具体办法, 2、 可以尝试采用迂回战术来回答,如“首先听取领导的指示和要求,然后就有关情况进行了解和熟悉,接下来制定一份近期的工作计划并报领导批准,最后根据计划开展工作。”
 
  问题十一:“与上级意见不一是,你将怎么办?”
 
  思路: 1、 一般可以这样回答“我会给上级以必要的解释和提醒,在这种情况下,我会服从上级的意见。” 2、 如果面试你的是总经理,而你所应聘的职位另有一位经理,且这位经理当时不在场,可以这样回答:“对于非原则性问题,我会服从上级的意见,对于涉及公司利益的重大问题,我希望能向更高层领导反映。”
 
  问题十二:“我们为什么要录用你?”
 
  思路: 1、 应聘者最好站在招聘单位的角度来回答。 2、 招聘单位一般会录用这样的应聘者:基本符合条件、对这份共组感兴趣、有足够的信心。 3、 如“我符合贵公司的招聘条件,凭我目前掌握的技能、高度的责任感和良好的饿适应能力及学习能力 ,完全能胜任这份工作。我十分希望能为贵 公司服务,如果贵公司给我这个机会,我一定能成为贵公司的栋梁!”

  问题十三:“你能为我们做什么?”
 
  思路: 1、 基本原则上“投其所好”。 2、 回答这个问题前应聘者最好能“先发制人”,了解招聘单位期待这个职位所能发挥的作用。 3、 应聘者可以根据自己的了解,结合自己在专业领域的优势来回答这个问题。
 
  问题十四:“你是应届毕业生,缺乏经验,如何能胜任这项工作?”
 
  思路: 1、 如果招聘单位对应届毕业生的应聘者提出这个问题,说明招聘单位并不真正在乎“经验”,关键看应聘者怎样回答。 2、 对这个问题的回答最好要体现出应聘者的诚恳、机智、果敢及敬业。 3、 如“作为应届毕业生,在工作经验方面的确会有所欠缺,因此在读书期间我一直利用各种机会在这个行业里做兼职。我也发现,实际工作远比书本知识丰富、复杂。但我有较强的责任心、适应能力和学习能力,而且比较勤奋,所以在兼职中均能圆满完成各项工作,从中获取的经验也令我受益非浅。请贵公司放心,学校所学及兼职的工作经验使我一定能胜任这个职位。”

  问题十五:“你希望与什么样的上级共事?”
 
  思路: 1、 通过应聘者对上级的“希望”可以判断出应聘者对自我要求的意识,这既上一个陷阱,又上一次机会。 2、 最好回避对上级具体的希望,多谈对自己的要求。 3、 如“做为刚步入社会新人,我应该多要求自己尽快熟悉环境、适应环境,而不应该对环境提出什么要求,只要能发挥我的专长就可以了。”
 
  问题十六:“您在前一家公司的离职原因是什么?”
 
  思路: 1、 最重要的是:应聘者要使找招聘单位相信,应聘者在过往的单位的“离职原因”在此家招聘单位里不存在。 2、 避免把“离职原因”说得太详细、太具体。 3、 不能掺杂主观的负面感受,如“太幸苦”、“人际关系复杂”、“管理太混乱”、“公司不重视人才”、“公司排斥我们某某的员工”等。 4、 但也不能躲闪、回避,如“想换换环境”、“个人原因”等。 5、 不能涉及自己负面的人格特征,如不诚实、懒惰、缺乏责任感、不随和等。 6、 尽量使解释的理由为应聘者个人形象添彩。 7、 如“我离职是因为这家公司倒闭。我在公司工作了三年多,有较深的感情。从去年始,由于市场形势突变,公司的局面急转直下。到眼下这一步我觉得很遗憾,但还要面对显示,重新寻找能发挥我能力的舞台。” 同一个面试问题并非只有一个答案,而同一个答案并不是在任何面试场合都有效,关键在于应聘者掌握了规律后,对面试的具体情况进行把握,有意识地揣摩面试官提出问题的心理背景,然后投其所好。
posted @ 2009-10-02 16:36 life02 阅读(167) | 评论 (0)编辑 收藏

// 编程珠玑 第二章 字符串string循环移位i位
// eg "abcdefgh" 循环移位 3位 =》 "defghabc"
#include<iostream.h>
#include 
<string.h>

char* string_cyclicshift_v2( char* stringint i )
{
    
char ch;
    
int exchange;
    
int len;
    
    exchange 
= 0;
    len 
= strlen( string );
    
    i 
= i%len;
    
if ( 0 == i )
        
return string;
    
    
int start_pos=0;
    
while ( exchange<len )
    
{
        
char ch = string[start_pos];
        
        
int currpos = start_pos;
        
int nextpos = (len+currpos+i)%len;
        
while ( nextpos != start_pos )
        
{
            
string[currpos] = string[nextpos];
            
++exchange;
            
            currpos 
= nextpos;
            nextpos 
= (len+currpos+i)%len;

        }

         cout
<<string<<endl;
        
string[currpos] = ch;
        
++exchange;
        
        
++start_pos;
    }

    
    
return string;
}


int main(){
    
char string[7]={'a','b','h','d','h','s'};
    cout
<<string<<endl;
    
char* s;
    s
=string_cyclicshift_v2(string,4);
    cout
<<s<<endl;

return 0;
}

要求时间复杂度空间复杂度都尽可能的低。

时间复杂度 O(n), 空间复杂度O(1),常量时间。

http://blog.csdn.net/zdl1016/archive/2009/09/21/4575309.aspx
posted @ 2009-09-28 23:02 life02 阅读(1192) | 评论 (1)编辑 收藏

#include<iostream.h>
#define N 13

void sift(int* a,int low,int high){
    
int i=low;
    
int j=2*i;
    
int temp=a[i];
    
while(j<=high){
          
if (j<high && a[j]<a[j+1])
          
{
              j
++;
          }

          
if (temp<a[j])
          
{
              a[i]
=a[j];
              i
=j;
              j
=2*i;
          }
else
              
break;

    }

    a[i]
=temp;
}


void heap_sort(int* a,int n){
   
int i;
   
int temp;
   
for (i=n/2;i>=0;i--)
   
{
       sift(a,i,n
-1);
   }

   
for (i=n-1;i>0;i--)
   
{
       temp
=a[0];
       a[
0]=a[i];
       a[i]
=temp;
       sift(a,
0,i-1);
   }


}


void sort_print(int* a,int n){
  
for (int i=0;i<n;i++)
  
{
      cout
<<a[i]<<" ";
  }

  cout
<<endl;

}


int main(){

    
int a[N]={34,34,566,66,77,8,989,6676,12323,89,90,123,4355};
    sort_print(a,N);
    heap_sort(a,N);
    sort_print(a,N);



}
posted @ 2009-09-28 22:28 life02 阅读(226) | 评论 (0)编辑 收藏

http://blog.163.com/pcteacher/blog/static/66585815200862183835111/


算法的力量(转李开复)---适合计算机专业新生

算法的力量
2006年5月

算法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员的冷落许多学生看到一些公司在招聘时要求的编程语言五花八门,就产生了一种误解,认为学计算机就是学各种编程语言,或者认为,学习最新的语言技术标准就是最好的铺路方法其实,大家被这些公司误导了编程语言虽然该学,但是学习计算机算法和理论更重要,因为计算机语言和开发平台日新月异,但万变不离其宗的是那些算法和理论,例如数据结构算法编译原理计算机体系结构关系型数据库原理等等在开复学生网上,有位同学生动地把这些基础课程比拟为内功,把新的语言技术标准比拟为外功整天赶时髦的人最后只懂得招式,没有功力,是不可能成为高手的

算法与我

当我在1980年转入计算机科学系时,还没有多少人的专业方向是计算机科学有许多其他系的人嘲笑我们说:知道为什么只有你们系要加一个科学,而没有物理科学系或化学科学系吗?因为人家是真的科学,不需要画蛇添足,而你们自己心虚,生怕不科学,才这样欲盖弥彰 其实,这点他们彻底弄错了真正学懂计算机的人(不只是编程匠)都对数学有相当的造诣,既能用科学家的严谨思维来求证,也能用工程师的务实手段来解决问题而这种思维和手段的最佳演绎就是算法

记得我读博时写的Othello对弈软件获得了世界冠军当时,得第二名的人认为我是靠侥幸才打赢他,不服气地问我的程序平均每秒能搜索多少步棋,当他发现我的软件在搜索效率上比他快60多倍时,才彻底服输为什么在同样的机器上,我可以多做60倍的工作呢?这是因为我用了一个最新的算法,能够把一个指数函数转换成四个近似的表,只要用常数时间就可得到近似的答案在这个例子中,是否用对算法才是能否赢得世界冠军的关键

还记得1988年贝尔实验室副总裁亲自来访问我的学校,目的就是为了想了解为什么他们的语音识别系统比我开发的慢几十倍,而且,在扩大至大词汇系统后,速度差异更有几百倍之多他们虽然买了几台超级计算机,勉强让系统跑了起来,但这么贵的计算资源让他们的产品部门很反感,因为昂贵的技术是没有应用前景的在与他们探讨的过程中,我惊讶地发现一个O(n*m)的动态规划(dynamic programming)居然被他们做成了O(n*n*m)更惊讶的是,他们还为此发表了不少文章,甚至为自己的算法起了一个很特别的名字,并将算法提名到一个科学会议里,希望能得到大奖当时,贝尔实验室的研究员当然绝顶聪明,但他们全都是学数学物理或电机出身,从未学过计算机科学或算法,才犯了这么基本的错误我想那些人以后再也不会嘲笑学计算机科学的人了吧!

网络时代的算法

有人也许会说:今天计算机这么快,算法还重要吗?其实永远不会有太快的计算机,因为我们总会想出新的应用虽然在摩尔定律的作用下,计算机的计算能力每年都在飞快增长,价格也在不断下降可我们不要忘记,需要处理的信息量更是呈指数级的增长现在每人每天都会创造出大量数据(照片,视频,语音,文本等等)日益先进的记录和存储手段使我们每个人的信息量都在爆炸式的增长互联网的信息流量和日志容量也在飞快增长在科学研究方面,随着研究手段的进步,数据量更是达到了前所未有的程度无论是三维图形海量数据处理机器学习语音识别,都需要极大的计算量在网络时代,越来越多的挑战需要靠卓越的算法来解决

再举另一个网络时代的例子在互联网和手机搜索上,如果要找附近的咖啡店,那么搜索引擎该怎么处理这个请求呢?

最简单的办法就是把整个城市的咖啡馆都找出来,然后计算出它们的所在位置与你之间的距离,再进行排序,然后返回最近的结果但该如何计算距离呢?图论里有不少算法可以解决这个问题

这么做也许是最直观的,但绝对不是最迅速的如果一个城市只有为数不多的咖啡馆,那这么做应该没什么问题,反正计算量不大但如果一个城市里有很多咖啡馆,又有很多用户都需要类似的搜索,那么服务器所承受的压力就大多了在这种情况下,我们该怎样优化算法呢?

首先,我们可以把整个城市的咖啡馆做一次预处理比如,把一个城市分成若干个格子(grid),然后根据用户所在的位置把他放到某一个格子里,只对格子里的咖啡馆进行距离排序

问题又来了,如果格子大小一样,那么绝大多数结果都可能出现在市中心的一个格子里,而郊区的格子里只有极少的结果在这种情况下,我们应该把市中心多分出几个格子更进一步,格子应该是一个树结构,最顶层是一个大格整个城市,然后逐层下降,格子越来越小,这样有利于用户进行精确搜索如果在最底层的格子里搜索结果不多,用户可以逐级上升,放大搜索范围

上述算法对咖啡馆的例子很实用,但是它具有通用性吗?答案是否定的把咖啡馆抽象一下,它是一个点,如果要搜索一个面该怎么办呢?比如,用户想去一个水库玩,而一个水库有好几个入口,那么哪一个离用户最近呢?这个时候,上述树结构就要改成r-tree,因为树中间的每一个节点都是一个范围,一个有边界的范围(参考:http://www.cs.umd.edu/~hjs/rtrees/index.html

通过这个小例子,我们看到,应用程序的要求千变万化,很多时候需要把一个复杂的问题分解成若干简单的小问题,然后再选用合适的算法和数据结构

并行算法:Google的核心优势

上面的例子在Google里就要算是小case了!每天Google的网站要处理十亿个以上的搜索,GMail要储存几千万用户的2G邮箱,Google Earth要让数十万用户同时在整个地球上遨游,并将合适的图片经过互联网提交给每个用户如果没有好的算法,这些应用都无法成为现实

在这些的应用中,哪怕是最基本的问题都会给传统的计算带来很大的挑战例如,每天都有十亿以上的用户访问Google的网站,使用Google的服务,也产生很多很多的日志(Log)因为Log每分每秒都在飞速增加,我们必须有聪明的办法来进行处理我曾经在面试中问过关于如何对log进行一些分析处理的问题,有很多面试者的回答虽然在逻辑上正确,但在实际应用中是几乎不可行的按照他们的算法,即便用上几万台机器,我们的处理速度都跟不上数据产生的速度

那么Google是如何解决这些问题的呢?

首先,在网络时代,就算有最好的算法,也要能在并行计算的环境下执行在Google的数据中心,我们使用的是超大的并行计算机但传统的并行算法运行时,效率会在增加机器数量后迅速降低,也就是说,十台机器如果有五倍的效果,增加到一千台时也许就只有几十倍的效果这种事倍功半的代价是没有哪家公司可以负担得起的而且,在许多并行算法中,只要一个结点犯错误,所有计算都会前功尽弃

那么Google是如何开发出既有效率又能容错的并行计算的呢?

Google最资深的计算机科学家Jeff Dean认识到, Google 所需的绝大部分数据处理都可以归结为一个简单的并行算法:Map and Reduce(http://labs.google.com/papers/mapreduce.html) 这个算法能够在很多种计算中达到相当高的效率,而且是可扩展的(也就是说,一千台机器就算不能达到一千倍的效果,至少也可以达到几百倍的效果)Map and Reduce的另外一大特色是它可以利用大批廉价的机器组成功能强大的server farm最后,它的容错性能异常出色,就算一个server farm里面的机器down掉一半,整个farm依然能够运行正是因为这个天才的认识,才有了Map and Reduce算法借助该算法,Google几乎能无限地增加计算量,与日新月异的互联网应用一同成长

算法并不局限于计算机和网络

举一个计算机领域外的例子:在高能物理研究方面,很多实验每秒钟都产生几个TB的数据量但因为处理能力和存储能力的不足,科学家不得不把绝大部分未经处理的数据丢弃掉可大家要知道,新元素的信息很有可能就藏在我们来不及处理的数据里面同样的,在其他任何领域里,算法都可以改变人类的生活例如人类基因的研究,就可能因为算法而发明新的医疗方式在国家安全领域,有效的算法可能避免下一个911的发生在气象方面,算法可以更好地预测未来天灾的发生,以拯救生命

所以,如果你把计算机的发展放到应用和数据飞速增长的大环境下,你一定会发现,算法的重要性不是在日益减小,而是在日益加强

给程序员的七个建议

(1)练内功不要只花功夫学习各种流行的编程语言和工具,以及某些公司招聘广告上要求的科目要把数据结构算法数据库操作系统原理计算机体系结构计算机网络,离散数学等基础课程学好大家不妨试试高德纳所著The Art of Computer Programming里的题目,如果你能够解决其中的大部分题目,就说明你在算法方面有一定的功力了

(2)多实战通过编程的实战积累经验巩固知识很多中国大学毕业生缺乏编程和调试经验;学习C语言,考试过关就算学会了;课题项目中,只要程序能够编译,运行,并且输入输出满足要求就算了事这些做法是不行的写程序的时候,大家必须多想想如何把程序写得更加精炼高效高质量建议大家争取在大学四年中积累编写十万行代码的经验我们必须明白的是:好程序员是写出来的,不是学出来的

(3)求实干不要轻视任何实际工作,比如一些看似简单的编码或测试要不懈追求对细节一丝不苟的实干作风与敬业精神我发现不少程序员对于知识的掌握很肤浅,不求甚解,没有好奇心,不会刨根问底比如,学会了C++,是否了解一个对象在编译后,在汇编代码中是如何被初始化的?这个对象的各个成员在内存中是如何存放的?当一个成员函数被调用时,编译器在汇编代码中加入了哪些额外的动作?虚函数的调用是如何实现的? 这些东西恐怕在编程语言或编译原理中都没有详细提到,只有通过踏实的实干才能真正掌握

(4)重视数学学习数学是思维的体操,数学无处不在学计算机至少要学习离散数学概率论布尔代数集合论和数理逻辑这些知识并不难,但是对你未来的工作帮助会很大 尤其当你对一些数学密集型的领域如视频图像处理等有兴趣时,这些知识将成为你手中的利器

(5)培养团队精神,学会与人合作今天的软件工程早已经不是一个人可以单独操作的,而必须靠团队合作才能成功不懂得合作的人是不能成大器的大家要多去寻找可以与人一起做项目的机会

(6)激励创新意识,培养好奇心,不要死记硬背没有掌握某种算法技术的根本原理,就不会有应变和创新的能力想成为一位好程序员(其实从事任何一个行业都是如此),重要的是要养成钻研,好奇,创新,动手,合作的优秀习惯,不满足于填鸭,不满足于考试交差,不满足于表象这不是学几门课能够一蹴而就的

(7)有策略地打工在不影响学业的前提下,寻找真正有意义的暑期工作或兼职去找一个重视技术的公司,在一个好的老板指导下完成真正会被用户使用的程序不要急于去一个要你做头而独挡一面的地方,因为向别人学习才是你的目的找工作也是一样,不要只看待遇和职衔,要挑一个你能够学习的环境,一个愿意培养员工的企业,一个重视你的专业的公司最后,还要挑一个好老板

希望大家都能把握机会,养成好的学习习惯,把算法学精学透;希望大家都能有一个美好的未来!

 该回复于2008-05-14 08:25:19被管理员删除  The Art of Computer Programming Vol.1 (中文译作计算机编程的艺术计算机程序设计技巧)--Basic Algorithms(基础算法)

这部书被誉为20世纪最重要的20部著作之一,与Einstein的相对论并列,使计算机科学领域的权威著作全书共分5卷,目前已经出版了3卷,这是它的第一卷基础算法,包含了我们常用的算法及其相关数据结构作者高德纳(Donald E. Knuth)是美国Stanford大学计算机科学系的退休教授,在计算机科学领域享有崇高的威望 


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zdl1016/archive/2009/09/27/4602750.aspx

posted @ 2009-09-28 09:47 life02 阅读(253) | 评论 (0)编辑 收藏

http://student.csdn.net/space.php?uid=32341&do=blog&id=1716

 1#include <stdio.h>    
 2int main(void)    
 3{    
 4    int n, nSum=1;// nSum 保存总和    
 5    scanf("%d"&n);// 输入要分解的n    
 6    for(int n1=1, n2=n1; n1<=n/2; )// n1为最开头的数,n2是最末尾    
 7    {    
 8        if(nSum<n)      //总和偏小    
 9        {    
10            n2++;       //末尾加数    
11            nSum+=n2;    
12        }
    
13        else if(nSum>n) //总和偏大    
14        {    
15            nSum -= n1; //开头删数    
16            n1++;    
17        }
    
18        else //if(nSum==n) //相等就输出结果    
19        {    
20            for(int t=n1; t<=n2; t++)    
21            {    
22                printf("%d,", t);    
23            }
    
24            printf("\n");    
25            n2++;       //末尾加数,如果不加就会死循环    
26            nSum+=n2;   //这步要小心    
27        }
    
28    }
    
29    return 0;    
30}
    
31

问题:还有更快的办法吗?请仔细观察第一段代码,看得出哪个特点可以利用不?

关键就在那个通项公式,(n1+n2)*(n2-n1+1) == n*2
这里如果先把n乘以2,然后的问题可不可以看成是因子分解?答案很明显。
假如分解出的结果是n*2 = a*b ,
那就解方程组 n1+n2=a, n2-n1+1=b
即n1=(a-b+1)/2, n2=(a+b-1)/2
如果解出的结果n1和n2是整数的话(即要使a和b一奇一偶),显然就得到一组解了
而因子分解的复杂度是O(sqrt(n)),显示会比之前第二段代码要节省非常多的时间。

posted @ 2009-09-28 09:03 life02 阅读(595) | 评论 (1)编辑 收藏

http://www.cnblogs.com/cgwolver/archive/2009/03/26/1257611.html
假定在右手坐标系中的三角形3点坐标为A,B,C,判断P是否在ABC之内

( 主要来自 3D引擎研发QQ群(38224573 )的各位朋友的讨论 ,我仅仅算做个总结吧,特别感谢各位朋友的热情支持。 )

方法1:三个Perplane的方法

           设AB,BC,AC边上的垂直平面为Perplane[3],垂直朝向内侧的法向为n[3]

          1)先根据任意两边叉出法向N

               N = AB.CrossProduct(AC);

               N.Normalize();

               D = A.DotProduct( N );

          2)如果P在三角形所在平面之外,可直接判定不在平面之内( 假定方程为 ax+by+cz+d = 0 )

               if( P.DotProduct( N ) + D > 0 ) return false;

          3)然后法向和各边叉出垂直平面的法向

               n[0] = N.CrossProduct(AB); //朝向内侧

               n[0].Normalize();

               Perplane[0].dist = A.DotProduct(n[0]);

               Perplane[0].normal = n[0];

               同样方法求得Perplane[1],Perlane[2];

          3)因为三个Perplane都朝向三角形内侧,P在三角形内的条件是同时在三个Perplane前面;如果给定点P在任意一个垂直平面之后,那么可判定P在三角形外部

               for( int i = 0;i<3;j++ )

               {

                    if( P.DotProduct( Perplane[i].normal ) + Perplane[i].dist < 0 )

                         return false;

               }

               return true;//如果P没有在任意一条边的外面,可判断定在三角形之内,当然包括在边上的情况

方法2:三个部分面积与总面积相等的方法

          S(PAB) + S(PAC) + S( PBC) = S(ABC) 则判定在三角形之内

          用矢量代数方法计算三角形的面积为

               S = 1/2*|a|*|b|*sin(theta)

                  = 1/2*|a|*|b|*sqrt(1-cos^2(theta))

                  = 1/2*|a|*|b|*sqrt(1- (a.DotProduct(b)/(|a|*|b|))^2);

               另一种计算面积的方法是 S = 1/2*|a.CrossProduct(b)|

               比较一下,发现后者的精确度和效率都高于前者,因为前者需要开方和求矢量长度,矢量长度相当于一次点乘,三个点乘加一个开方,显然不如

               后者一次叉乘加一次矢量长度(注,一次叉乘计算相当于2次点乘,一次矢量长度计算相当于一次点乘),后者又对又快。

               

               S(ABC)  = AB.CrossProduct(AC);//*0.5;

               S(PAB)  = PA.CrossProduct(PB);//*0.5;

               S(PBC)  = PB.CrossProduct(PC);//*0.5;

               S(PAC)  = PC.CrossProduct(PA);//*0.5;

               if( S(PAB) + S(PBC) + S(PAC) == S(ABC)  )

                    return true;

               return false;

         

        另一种计算三角形面积的矢量方法是 1/2*a.CrossProdcuct(b) ,CrossProduct = ( y1*z2 - y2*z1 , x1*z2 - x2*z1, x1*y2 - x2*z1 )

               可以看到CrossProduct 的计算要比DotProduct多3个乘法计算,效率没有上面的方法高


方法3:三个向量归一化后相加为0

        这个方法很怪异,发现自http://flipcode.spaces.live.com/blog/cns!8e578e7901a88369!903.entry 下面的一个回帖

                 
              

          如上图三角形ABC,P为AB外侧一点,N1,N2,N3 分别为BP,AP,CP的归一化矢量;NM为N1,N2夹角的角平分线

          可以看出角A-P-B是三角形内角,必然小于180度,那么角N1-P-N2等于A-P-B;NM是N1-P-N2的角平分线,那么角B-P-N等于角N-P-A,而CPN必然小于其中一个,

          即小于180/2 = 90度。结论是角N1,N2的合矢量方向与N3的夹角为锐角。所以N1,N2,N3的合向量模大于1.

          这里注意,N3不一定在N1,N2之间,不能假定N2-P-N3 和N3-P-N1这两个角一定是锐角

          同样可以推导出如果P在三角形内,N1+N2+N3必然小于0;若N1+N2+N3 = 0则P在三角形的边上。

          有没有更简单的推导方法?

         

          这个方法看起来很精巧,但是善于优化的朋友会立刻发现,三个矢量归一化,需要三个开方。迭代式开方太慢了,而快速开方有的时候又不满足精度要求。

                 

 方法4:重心坐标之和为1

         {

               BaryCenter = ( S(PAB)/S(PABC),S(PBC)/S(PABC),S(PAC)/S(PABC)) // 点P在三角形内的重心坐标

         

               if( BaryCenter.x + BaryCenter.y + BaryCenter.z >0.f )

                    return false

               return true;

          }

          其中S(PAB),S(ABC),S(PBC),S(PBC) 用上述的方法二种提到的计算三角形面积方法计算。

综合比较

     方法1必须求叉乘,虽然可以通过首先排除不在平面内的点,但是后面仍要求三个叉乘和3个点乘(当然还可排除法优化)

     方法2看起来之需要求4个点乘,如果用叉乘方法计算面积,可能会导致效率低下

     方法3是看起来是最精巧的方法,但是效率也不能保证...3个开方

     方法4和方法2的效率差不多

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/boyzk2008/archive/2009/08/07/4421106.aspx

posted @ 2009-09-25 10:22 life02 阅读(1598) | 评论 (8)编辑 收藏

一.  单选题(每题4分,15题,共60分)

  1.考虑函数原型void hello(int a,int b=7,char* pszC="*"),下面的函数调用钟,属于不合法调用的是:

  A hello(5)     B.hello(5,8)     C.hello(6,"#")     D.hello(0,0,"#")

  2.下面有关重载函数的说法中正确的是:

  A.重载函数必须具有不同的返回值类型   B.重载函数形参个数必须不同

  C.重载函数必须有不同的形参列表       D.重载函数名可以不同

  3.分析一下程序的运行结果:

  #include<iostream.h>

  class CBase

  {

  public:

  CBase(){cout<<”constructing CBase class”<<endl;}

  ~CBase(){cout<<”destructing CBase class”<<endl;}

  };

  class CSub : public CBase

  {

  public:

  CSub(){cout<<”constructing CSub class”<<endl;}

  ~CSub(){cout<<”destructing CSub class”<<endl;}

  };

  void main()

  {

  CSub obj;

  }

  A. constructing CSub class           B. constructing CBase class

  constructing CBase class             constructing CSub class

  destructing CSub class               destructing CBase class

  destructing CBase class              destructing CSub class

  C. constructing CBase class

  constructing CSub class

  destructing CSub class

  destructing CBase class

  D. constructing CSub class

  constructing CBase class

  destructing CBase class

  destructing CSub class

  4.在一个cpp文件里面,定义了一个static类型的全局变量,下面一个正确的描述是:

  A.只能在该cpp所在的编译模块中使用该变量

  B.该变量的值是不可改变的

  C.该变量不能在类的成员函数中引用

  D.这种变量只能是基本类型(如int,char)不能是C++类型

  5.观察下面一段代码:

  class ClassA

  {

  public:

  virtual ~ ClassA(){};

  virtual void FunctionA(){};

  };

  class ClassB

  {

  public:

  virtual void FunctionB(){};

  };

  class ClassC : public ClassA,public ClassB

  {

  public:

  };

  ClassC aObject;

  ClassA* pA=&aObject;

  ClassB* pB=&aObject;

  ClassC* pC=&aObject;

  关于pA,pB,pC的取值,下面的描述中正确的是:

  A.pA,pB,pC的取值相同.               B.pC=pA+pB

  C.pA和pB不相同                      D.pC不等于pA也不等于pB

  6.参照1.5的代码,假设定义了ClassA* pA2,下面正确的代码是:

  A.pA2=static_cast<ClassA*>(pB);

  B.void* pVoid=static_cast<void*>(pB);

  pA2=static_cast<ClassA*>(pVoid);

  C.pA2=pB;

  D.pA2=static_cast<ClassA*>(static_cast<ClassC*>(pB));

  7.参照1.5的代码,下面那一个语句是不安全的:

  A.delete pA   B.delete pB   C.delete pC

  8.下列程序的运行结果为:

  #include<iostream.h>

  void main()

  {

  int a=2;

  int b=++a;

  cout<<a/6<<endl;

  }

  A.0.5   B.0   C0.7   D.0.6666666-

  9.有如下一段代码:

  #define ADD(x,y) x+y

  int m=3;

  m+=m*ADD(m,m);

  则m的值为:

  A.15   B.12   C.18   D.58

  10.如下是一个带权的图,图中结点A到结点D的关键路径的长度是:

  A.13       B.15       C.28       D.58

  11.下面的模板声明中,正确的是:

  A.template<typename T1,T2>

  B.template<class T1,T2>

  C.template<class T1,class T2>

  D.template<typename T1;typename T2>

  12.在Windows编程中下面的说法正确的是:

  A.两个窗口,他们的窗口句柄可以是相同的     B.两个窗口,他们的处理函数可以是相同的

  C.两个窗口,他们的窗口句柄和窗口处理函数都不可以相同.

  13.下面哪种情况下,B不能隐式转换为A?

  A.class B:public A{}                 B.class A:public B{}
C.class B{operator A();}             D.class A{A(const B&);}

  14.某公司使用包过滤防火墙控制进出公司局域网的数据,在不考虑使用代理服务器的情况下,下面描述错误的是”该防火墙能够(   )”.

  A.使公司员工只能访问Internet上与其业务联系的公司的IP地址.

  B.仅允许HTTP协议通过,不允许其他协议通过,例如TCP/UDP.

  C.使员工不能直接访问FTP服务器端口号为21的FTP地址.

  D.仅允许公司中具有某些特定IP地址的计算机可以访问外部网络

  15.数字字符0的ASCII值为48,若有以下程序:

  main()

  {

  char a=’1’,b=’2’;

  printf(“%c,”,b++);

  printf(“%d\n”,b-a);

  }

  程序运行之后的输出结果是:

  A.3,2      B.50,2       C.2,2     D.2,50

  二.  填空题(共40分)

  本程序从正文文件text.in读入一篇英文短文,统计该短文中不同单词和它的出现次数,并按词典编辑顺序将单词及它的出现次数输出到正文文件word.out中.

  程序用一棵有序二叉树存储这些单词及其出现的次数,一边读入一边建立.然后中序遍历该二叉树,将遍历经过的二叉树上的节点的内容输出.
程序中的外部函数

  int getword(FILE* pFile,char* pszWordBuffer,int nBufferLen);

  从与pFile所对应的文件中读取单词置入pszWordBuffer,并返回1;若单词遇文件尾,已无单词可读时,则返回0.

  #include <stdio.h>

  #include <malloc.h>

  #include <ctype.h>

  #include <string.h>

  #define SOURCE_FILE "text.in"

  #define OUTPUT_FILE "word.out"

  #define MAX_WORD_LEN 128

  typedef struct treenode

  {

  char szWord[MAX_WORD_LEN];

  int nCount;

  struct treenode* pLeft;

  struct treenode* pRight;

  }BNODE;

  int getword(FILE* pFile,char* pasWordBuffer,int nBufferLen);

  void binary_tree(BNODE** ppNode,char* pszWord)

  {

  if(ppNode != NULL && pszWord != NULL)

  {

  BNODE* pCurrentNode = NULL;

  BNODE* pMemoNode = NULL;

  int nStrCmpRes=0;

  ____(1)_____;pCurrentNode=*ppNode

  while(pCurrentNode)

  {

  /*寻找插入位置*/

  nStrCmpRes = strcmp(pszWord, ___(2)___ );pCurrentNode->nCount

  if(!nStrCmpRes)

  {

  ___(3)___; pCurrentNode->nCount++

  return;

  }

  else

  {

  ___(4)___; pMemoNode=pCurrentNode

  pCurrentNode = nStrCmpRes>0? pCurrentNode->pRight : pCurrentNode->pLeft;

  }

  }

  }

  pCurrent=new BNODE;

  if(pCurrentNode != NULL)

  {

  memset(pCurrentNode,0,sizeof(BNODE));

  strncpy(pCurrentNode->szWord,pszWord,MAX_WORD_LEN-1);

  pCurrentNode->nCount=1;

  }

  if(pMemoNode==NULL)

  {

  ___(5)___; *ppNode= pCurrentNode

  }

  else if(nStrCmpRes>0)

  {

  pMemoNode->pRight=pCurrentNode;

  }

  else

  {

  pMemoNode->pLeft=pCurrentNode;

  }

  }

  void midorder(FILE* pFile,BNODE* pNode)

  {

  if(___(6)___) return;!pNode||!pFile

  midorder(pFile,pNode->pLeft);

  fprintf(pFile,"%s %d\n",pNode->szWord,pNode->nCount);

  midorder(pFile,pNode->pRight);

  }

  void main()

  {

  FILE* pFile=NULL;

  BNODE* pRootNode=NULL;

  char szWord[MAX_WORD_LEN]={0};

  pFile=fopen(SOURCE_FILE,"r");

  if(pFile==NULL)

  {

  printf("Can't open file %s\n",SOURCE_FILE);

  return;

  }

  while(getword(pFile,szWord,MAX_WORD_LEN)==1)

  {

  binary_tree(___(7)___);// pRootNode,szWord

  }

  fclose(pFile);

  pFile=fopen(OUTPUT_FILE,"w");

  midorder(pFile,pRootNode);

  fclose(pFile);

  }

  三.  附加题(每题30分,2题,共60分)

  1.      从程序健壮性进行分析,下面的FillUserInfo函数和Main函数分别存在什么问题?

  #include <iostream>

  #include <string>

  #define MAX_NAME_LEN 20

  struct USERINFO

  {

  int nAge;

  char szName[MAX_NAME_LEN];

  };

  void FillUserInfo(USERINFO* parUserInfo)

  {

  stu::cout<<"请输入用户的个数:";

  int nCount=0;

  std::cin>>nCount;

  for(int i=0;i<nCount;i++)

  {

  std::cout<<"请输入年龄:";

  std::cin>>parUserInfo[i]->nAge;

  std::string strName;
std::cout<<"请输入姓名:";

  std::cin>>strName;

  strcpy(parUserInfo[i].szName,strName.c_str());

  }

  }

  int main(int argc,char* argv[])

  {

  USERINFO arUserInfos[100]={0};

  FillUserInfo(arUserInfos);

  printf("The first name is:");

  printf(arUserInfos[0].szName);

  printf("\n");

  return 0;

  }

  2.      假设你在编写一个使用多线程技术的程序,当程序中止运行时,需要怎样一个机制来安全有效的中止所有的线程?请描述其具体流程.


posted @ 2009-09-23 20:50 life02 阅读(528) | 评论 (0)编辑 收藏

#include <iostream>
using namespace std;

typedef 
struct node{
    
int key;
    
int data;
    
struct node *lchild,*rchild;
}
;

node
* bt=NULL;

int insertbst(node *&p,int k){
    
if (p==NULL)
    
{
        p
=(node*)malloc(sizeof(node));
        p
->key=k;
        p
->lchild=p->rchild=NULL;
        
return 1;
    }

    
else if (k==p->key)
    
{
        
return 0;
    }
else if (k<p->key)
    
{
        
return insertbst(p->lchild,k);
    }
else
    
{
        
return insertbst(p->rchild,k);
    }

}


node
* creatbst(int* a,int n){
    
    
int i=0;
    
while(i<n){
        insertbst(bt,a[i]);
        
++i;
    }

    
return bt;
}


void preorder(node* bt){
    
if (bt!=NULL)
    
{
        cout
<<bt->key<<endl;
        preorder(bt
->lchild);
        preorder(bt
->rchild);
    }

}




int main(){
    
int a[5]={12,3,4,8,10};
    node
* bl=new node();
    bl
=creatbst(a,5);
    preorder(bt);

    
return 0;
}
posted @ 2009-09-21 22:46 life02 阅读(138) | 评论 (0)编辑 收藏

http://blog.csdn.net/robinfoxnan/archive/2008/07/25/2712030.aspx
1. 简单实现
如果不管效率,最简单的实现只需要4行代码:

1 size_t strlen_a(const char * str) {
2     size_t length = 0 ;
3     while (*str++ )
4         ++ length;
5     return  length;
6 }
也许可以稍加改进如下:


1 size_t strlen_b(const char * str) {
2     const char *cp =  str;
3     while (*cp++ )
4          ;
5     return (cp - str - 1 );
6 }

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/robinfoxnan/archive/2008/07/25/2712030.aspx

posted @ 2009-09-21 22:18 life02 阅读(357) | 评论 (0)编辑 收藏

仅列出标题
共20页: First 12 13 14 15 16 17 18 19 20