2012年投商务搜索部的面试:
1 英文句子求逆序,但每个词不能逆序。
C版本(只能利用数组):
void reverseconvert(char *input,int length)
{
if(length>0)
{
char temp;
//颠倒整个数组!
for(int i=length-1;i>length/2-1;i--)
{
temp=input[i];
input[i]=input[length-1-i];
input[length-1-i]=temp;
}
cout<<input<<endl;
//颠倒每个单词
int first=0;
int second=0;
while(true)
{
if(first>=length)
break;
///找到一个单词的起始位置
for(int i=first;i<length;i++)
{
if(input[i]==' ')
{
second=i-1;
break;
}
if(i==length-1)
return;
}
//颠倒一个单词
for(int i=0;i<(second-first)/2+1;i++)
{
temp=input[i+first];
input[i+first]=input[second-i];
input[second-i]=temp;
}
first=second+2;
second=first;
}
}
}
C++版本(利用string)
void reverseconvert(string& input)
{
int length=input.length();
string::iterator first=input.begin();
unsigned int first1=0;
string::iterator second=first;
reverse(input.begin(),input.end()); 注意参数是迭代器!!并且reverse方法是通用函数,而不是string的内部函数!!!!
while(true)
{
string::size_type idx;
idx=input.find_first_of(" ",first1);
/参数2的选择是索引,而不是迭代器,这也是声明变量first1的原因!!!!返回值也是索引,这里面的核心是迭代器和索引的互相转换问题!!!!
if(idx==string::npos)
break;
else
{
second=input.begin()+idx;迭代器加上索引得到迭代器
first1=idx+1+first1;//first1始终记录索引
reverse(first,second);
first=second+1;
second=first;
}
}
}
singleton类
Singleton模式 VS全局变量。很多情况下,我们使用Singleton模式达到的效果和
全局变量达到的效果类似。但是,全局变量不能防止实例化多个对象。GoF在《设计模式》中给出了Singleton模式的意图“保证一个类仅有一个对象,并提供一个访问它的全局访问点”,因此全局变量可以达到后面半句的效果,但是却不能保证仅有一个对象被实例化。另外,使用全局变量将使得对象在无论是否用到都要被创建,而Singleton模式则没有这个瑕疵。
1. 标准的实现
class Singleton
{
public:
static Singleton * Instance()
{
if( 0== _instance)
{
_instance = new Singleton;
}
return _instance;
}
protected:
Singleton(void)
{
}
virtual ~Singleton(void)
{
}
static Singleton* _instance=0;
};
这是教科书上使用的方法。看起来没有什么问题,其实包含很多的问题。下面我们一个一个的解决。
或者查看http://www.cppblog.com/localvar/archive/2011/02/11/139892.html 这个方法比较简单,貌似线程安全!注意volatile的用法!!!
2. 自动垃圾回收
上面的程序必须记住在程序结束的时候,释放内存。为了让它自动的释放内存,我们引入auto_ptr改变它。
#include <memory>
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton * Instance()
{
if( 0== _instance.get())
{
_instance.reset(new Singleton);
}
return _instance.get();
}
protected:
Singleton(void)
{
cout <<"Create Singleton"<<endl;
}
virtual ~Singleton(void)
{
cout << "Destroy Singleton"<<endl;
}
friend class auto_ptr<Singleton>;
static auto_ptr<Singleton> _instance;
};
//Singleton.cpp
auto_ptr<Singleton> Singleton::_instance;
3 线程安全
上面的程序可以适应单线程的程序。但是如果把它用到多线程的程序就会发生问题。主要的问题在于同时执行_instance.reset(new T);就会同时产生两个新的对象,然后马上释放一个,这跟Singleton模式的本意不符。所以,你需要更加安全的版本:
/********************************************************************
(c) 2003-2005 C2217 Studio
Module: Singleton.h
Author: Yangjun D.
Created: 9/3/2005 23:17
Purpose: Implement singleton pattern
History:
*********************************************************************/
#pragma once
#include <memory>
using namespace std;
#include "Interlocked.h"
using namespace C2217::Win32;
namespace C2217
{
namespace Pattern
{
template <class T>
class Singleton
{
public:
static inline T* instance();
private:
Singleton(void){}
~Singleton(void){}
Singleton(const Singleton&){}
Singleton & operator= (const Singleton &){}
static auto_ptr<T> _instance;
static CResGuard _rs;
};
template <class T>
auto_ptr<T> Singleton<T>::_instance;
template <class T>
CResGuard Singleton<T>::_rs;
template <class T>
inline T* Singleton<T>::instance()
{
if( 0 == _instance.get())
{
CResGuard::CGuard gd(_rs);
if( 0== _instance.get())
{
_instance.reset(new T);
}
}
return _instance.get();
}
//Class that will implement the singleton mode,
//must use the macro in it's delare file
#define DECLARE_SINGLETON_CLASS( type) \
friend class auto_ptr< type >;\
friend class Singleton< type >;
}
}
CresGuard 类主要的功能是线程访问同步,代码如下:
/******************************************************************************
Module: Interlocked.h
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/
#pragma once
///
// Instances of this class will be accessed by multiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.
class CResGuard {
public:
CResGuard() { m_lGrdCnt = 0; InitializeCriticalSection(&m_cs);}
~CResGuard(){ DeleteCriticalSection(&m_cs);}
// IsGuarded is used for debugging
BOOL IsGuarded() const { return(m_lGrdCnt>0);}
public:
class CGuard {
public:
CGuard(CResGuard& rg): m_rg(rg){ m_rg.Guard();};
~CGuard(){ m_rg.Unguard();}
private:
CResGuard& m_rg;
};
private:
void Guard() { EnterCriticalSection(&m_cs); m_lGrdCnt++;}
void Unguard(){ m_lGrdCnt--; LeaveCriticalSection(&m_cs);}
// Guard/Unguard can only be accessed by the nested CGuard class.
friend class CResGuard::CGuard;
private:
CRITICAL_SECTION m_cs;
long m_lGrdCnt; // # of EnterCriticalSection calls
};
3 设计一个栈,使得push,pop,min操作的时间复杂度都在O(1)
4 问一个海量词库,给你一个词,怎么找到这个词的兄弟词,兄弟词就是字母组成相同,顺序不同。
刚开始说用hash,他说这方法可以,但对于一个海量词库,每次查都要遍历,效率低,问还有没有更好的。
我突然想到之前好像看过这题,就说可以给每个字母设定一个素数,那么一个单词的key就是组成字母对应素数的乘积,然后用这个key做hash,面试官还比较满意。这时旁听的小哥说话了,能不能先对词库做预处理?我说可以用key值做键值生成B+树,他又问那对于键值相同的词怎么处理,我说可以把他们连成链表,他对于这个答案还比较满意。
上面这道题,本人想法: 构造决策树,关于是否有这个字符开始。。。。(最多26层,就将结束 2的26次方)
5 判断两棵树是否相等,包括结构,每个节点的key值
6 写一个strncmp或者strcmp。