[微软面试100题]81-90

第八十一题:

1、求数组中大于左边所有元素,小于右边素有元素的数。只能用一个额外数组。

思路:从左往右遍历先把max记录在额外数组中。从右往左遍历记录当前min在一个变量中。对比min和max和当前即可。

//复杂度O(n),2次迭代,使用1个数组
void helper(int *a,int n){
    int nowmax=a[0],nowmin=a[n-1];
    int max[n];
    for(int i=0;i<n;++i){
        if(a[i]>nowmax)nowmax=a[i];
        max[i]=nowmax;
    }
    for(int i=n-1;i>=0;--i){
        if(a[i]<nowmin)nowmin=a[i];
        if(a[i]>=max[i] && a[i]<=nowmin)cout<<a[i]<<endl;
    }
}

2、一千万条字符串,找出所有系相反的字符串。

思路:先hash所有字符串,然后一条一条翻转再hash,冲突则输出即可。

第八十二题:

1、用C++模拟类似SQL的存储以及查询功能

class col
{
public:
    string name;
    int age;
    int index;
    static int nowindex;
    col(string name,int age);
};
int col::nowindex=0;//静态成员类外初始化
class table
{
    vector<col> cols;//用序号对vector随机存取
    map<string,int> name2index;//用一个hashtable关联名字和序号
public:
    void insert(string name,int age);
    int find_age(string name);
    void find_name(char c,int age);
};
col::col(string name,int age){
    index=nowindex;
    nowindex++;
    this->name=name;
    this->age=age;
}
void table::insert(string name,int age){
    col tmp(name,age);
    cols.push_back(tmp);
    name2index[name]=tmp.index;
}
int table::find_age(string name){
    if(name2index.find(name)!=name2index.end()){//判断map元素是否存在方法
    int index=name2index[name];
    return cols[index].age;
    }
    return -1;
}
void table::find_name(char c,int age){
    int len=cols.size();
    bool has_result=false;
    if(c=='='){
        for(int i=0;i<len;++i)
            if(cols[i].age==age){
                has_result=true;
                cout<<cols[i].name<<endl;
            }
    }else if(c=='>'){
        for(int i=0;i<len;++i)
            if(cols[i].age>age){
                has_result=true;
                cout<<cols[i].name<<endl;
            }
    }else if(c=='<'){
        for(int i=0;i<len;++i)
            if(cols[i].age<age){
                has_result=true;
                cout<<cols[i].name<<endl;
            }
    }else cout<<"error"<<endl;
    if(!has_result)cout<<"not found"<<endl;
}

 2、100亿条记录,包括两个字段{URL,SIZE},用shell抓取出包含baidu的size,并根据size排名

shell以后再复习。。。忘记了。。

思路:如果是C++的话,先找出含有baidu的,然后用堆排序。

第八十三题:实现memcpy函数

PS:注意区间重叠的情况即可

void* memmove(void* dest,const void* src,size_t n){
    if(dest==NULL || src==NULL)return NULL;
    char* byte_src=(char*)src;
    char* byte_dest=(char*)dest;
    int step=1;
    if((size_t)dest<(size_t)src+n){//防止原内存区间与目标区间重叠
        byte_src+=n-1;
        byte_dest+=n-1;
        step=-1;
    }//目标区间比原区间后,则需从最后开始复制
    //虽然重叠但目标在原区间前,则不会冲突
    for(size_t i=0;i<n;++i){
        *byte_dest=*byte_src;
        byte_dest+=step;
        byte_src+=step;
    }
    return dest;
}

 第八十四题:

1、用最快的方法找出相同的字符串

思路:(1)hash(2)字典树

2、字符串中子串的个数

思路:(1)从左往右扫不断对比,复杂度O(mn);(2)从左往右的hash,复杂度O(m)

第八十六题:二叉树存放有序数组

思路:死记硬背不好,只要那个1到7的数组写出它的前序、中序、后序遍历二叉树就知道程序怎么写了。

//前序遍历顺序。根节点是第一个元素,后面的元素分开两半,分别递归即可。
void BinaryTreeNode::buildfirst(int *a,int n){
    this->m_nValue=a[0];
    int lenleft=(n-1)/2;
    if(lenleft>0){
        this->m_pLeft=new BinaryTreeNode;
        this->m_pLeft->buildfirst(a+1,lenleft);
    }
    if(n-1-lenleft>0){
        this->m_pRight=new BinaryTreeNode;
        this->m_pRight->buildmid(a+1+lenleft,n-lenleft-1);
    }
}
//中序遍历顺序。根节点是中间元素,前后两段元素分别递归即可。
void BinaryTreeNode::buildmid(int *a,int n){
    int mid=n/2;
    this->m_nValue=a[mid];
    if(mid>0){
        this->m_pLeft=new BinaryTreeNode;
        this->m_pLeft->buildmid(a,mid);
    }
    if(n-mid-1>0){
        this->m_pRight=new BinaryTreeNode;
        this->m_pRight->buildmid(a+mid+1,n-mid-1);
    }
}
//后序遍历顺序。根节点是最后一个元素,前面的元素分开两半,分别递归即可。
void BinaryTreeNode::buildlast(int *a,int n){
    this->m_nValue=a[n-1];
    int lenleft=(n-1)/2;
    if(lenleft>0){
        this->m_pLeft=new BinaryTreeNode;
        this->m_pLeft->buildlast(a,lenleft);
    }
    if(n-1-lenleft>0){
        this->m_pRight=new BinaryTreeNode;
        this->m_pRight->buildlast(a+lenleft,n-lenleft-1);
    }
}

 第八十七题:大数相乘

思路:用字符串逐位相乘,累加到结果的数组中。最后处理结果数组考虑进位。

string muti(string s1,string s2){
    int len1=s1.length(),len2=s2.length();
    int *i1=new int[len1];
    int *i2=new int[len2];
    int *result=new int[len2+len1];
    memset(result,0,(len1+len2)*sizeof(int));
    for(int i=0;i<len1;++i)
        i1[i]=s1[len1-i-1]-'0';
    for(int i=0;i<len2;++i)
        i2[i]=s2[len2-i-1]-'0';

    for(int i=0;i<len1;i++){
        for(int j=0;j<len2;j++)
            result[i+j]+=i1[i]*i2[j];
    }
    for(int i=0;i<len1+len2;++i){
        if(result[i]>9){
            result[i+1]+=result[i]/10;
            result[i]=result[i]%10;
        }
    }
    string str;
    bool flag=true;
    for(int i=len1+len2-1;i>=0;--i){
        if(flag && result[i]==0)continue;
        flag=false;
        str+=result[i]+'0';
    }
    delete [] i1;
    delete [] i2;
    delete [] result;
    return str;
}

 大数相加:

string add(string s1,string s2){
    int len1=s1.length(),len2=s2.length();
    int *i1=new int[len1];
    int *i2=new int[len2];
    int len3=len1>len2?len1+1:len2+1;
    int *result=new int[len3];
    memset(result,0,len3*sizeof(int));
    for(int i=0;i<len1;++i)
        i1[i]=s1[len1-i-1]-'0';
    for(int i=0;i<len2;++i)
        i2[i]=s2[len2-i-1]-'0';

    for(int i=0;i<len3-1;i++){
        if(len1<len2 && i>=len1)
            result[i]=i2[i];
        else if(len2<len1 && i>=len2)
            result[i]=i1[i];
        else result[i]=i1[i]+i2[i];
    }for(int i=0;i<len3;++i){
        if(result[i]>9){
            result[i+1]+=result[i]/10;
            result[i]=result[i]%10;
        }
    }
  string str; bool flag=true; for(int i=len3-1;i>=0;--i){ if(flag && result[i]==0)continue; flag=false; str+=result[i]+'0'; } delete [] i1; delete [] i2; delete [] result; return str; }

 第八十八题:把*移到字符串前部

思路:记录两个坐标,一个是最后一个星,一个是最后一个字母。从后往前扫,扫到字母就与最后一个星交换。

int helper(char *s){
    int len=strlen(s);
    int i=len-1,j=len-1,count=0;
    while(j>=0){//j往前扫,直到不是*,i的位置一定是最后一个*
        if(s[j]!='*'){
            swap(s,i--,j--);//交换了以后,i-1肯定是*
            //如2个*连续则交换后显然是*;只有1个*的话,下一个就是刚交换的*
        }else{
            count++;
            j--;
        }
    }
    return count;
}

 第八十九题:删除字符串中的数字

思路:与上题基本一致。while循环一次做cursor移动一步,不要再用while,否则代码不简洁。

bool is_digit(char c){
    return (c>='0' && c<='9')?true:false;
}
char* helper(char *s){
    int i=0,j=0;
    while(s[j]!='\0'){
        if(!is_digit(s[j]))s[i++]=s[j++];
        else j++;
    }
    s[i]='\0';
    return s;

 第九十题:不使用临时空间翻转字符串

//模拟一个栈,如果只是翻转输出的话
void helper(char *s,int i,int n){
    if(i<n-1){
        helper(s,i+1,n);//没到最后,先递归
        cout<<s[i]<<endl;//递归完说明此元素之后的元素已经处理完毕,可处理此元素了
    }
    else cout<<s[i]<<endl;//最后的元素,停止递归
}

void helper2(char *s,int n){
    int i=0,j=n-1;
    while(j>i){
        char tmp=s[i];
        s[i]=s[j];
        s[j]=tmp;
        ++i;
        --j;
    }
}
//如何真的连一个char都不能申请只能使用
//想起一种不借助临时变量交换变量的方法
void helper3(char *s,int n){
    int i=0,j=n-1;
    while(j>i){
        s[i]^=s[j];//左包含ij的与或
        s[j]^=s[i];//右包含jij=i
        s[i++]^=s[j--];//左包含iji=j
    }
}

 

 

posted @ 2013-03-29 10:59  iyjhabc  阅读(311)  评论(0编辑  收藏  举报