[微软面试100题]21-30

第二十一题:输入m、n,打印出1~n中所有和等于m的组合(01背包问题)

递归法:
void printSolution(int *flag){
    for(int i=1;i<100;++i)
        if(flag[i]!=0)cout<<i<<" ";
    cout<<endl;
}
void bao(int m,int n,int *flag){
    if(m<1 || n<1)return;
    if(n>m)n=m;
    if(n==m){//end , print it
        flag[n]=1;
        printSolution(flag);
        flag[n]=0;
    }
    flag[n]=1;//select n
    bao(m-n,n-1,flag);
    flag[n]=0;
    bao(m,n-1,flag);//not select n
}

动态规划:适用于寻找最大值的情况。但需要打印出所有值时比较复杂。

第二十四题:合并但链表
先把原来的两个链表排序,然后在搞两个指针代表两个链表的当前节点。比较两个节点后决定新链表的新节点连接哪个,连了以后指向下一个节点。没什么好说的。。。想不通看会源代码。

第二十五题:找出最长的连续数字子串

一个变量记录当前最长字符串,一个变量记录全局最长字符串
bool is_digit(char c){
    if(c>='0' && c<='9')return true;
    return false;
}
 
void strcpy(const char *from,char *to,int count){
    for(int i=0;i<count;++i) to[i]=from[i];
    to[count]='\0';
}
 
void printstr(const char* str){
    const char* p=str;
    while(*p!='\0')cout<<*p++;
    cout<<endl;
}
 
int continuemax(char *outputstr,const char *inputstr){
    const char* pmax;
    int max=0,thismax=0;
    const char *p=inputstr;
    bool meetUnNum=false;
    while(true){
        if(meetUnNum){
            meetUnNum=false;
            thismax=0;
        }
        if(!is_digit(*p)){
            meetUnNum=true;
            if(thismax>max){
                max=thismax;
                pmax=p-max;
            }
        }else thismax++;
        if(*p++=='\0')break;
    }
    strcpy(pmax,outputstr,max);
    return max;
}

第二十六题:左旋字符串

使用之前reversestring的函数,进行反转再反转。第一次翻转复杂度为O(n/2),再翻转也是,总共就O(n)
 
第二十七题:n级楼梯,一次可以跳一步或者两步,一共有多少种跳法
第k个台阶的时候,可以从第k-1跳一步到达,也可以从k-2步跳2步到达。也就是是f(n)=f(n-1)+f(n-2),也就是裴波拉奇数列。用动态规划解决。
 
第二十八题:判断一个整数的二进制数中1的个数
法1:除以2看余数是否为1,是则加一,直到0.
法2:右移一位,判断最低位是否为1,是则加一。O(k),k is the bit length of int
int countOne2(int n){
    int cnt=0;
    while(n){
        if(n&1!=0)cnt++;
        n>>=1;
    }
    return cnt;
}

法3:n & n-1会将最低位的1变成0,如 1010 % 1001 = 1000,不断操作直至n=0,每次操作count+1. O(k),k is the number of 1 in n

int countOne3(int n){
    int cnt=0;
    while(n){
        cnt++;
        n&=n-1;
    }
    return cnt;
}

第二十九题:判断一个序列是否是一个push序列的pop序列

根据堆栈的性质用一个stack来模拟看能否全部用上两个序列即可
int judgeStackSequence(int *push,int *pop,int count){
    int iPop=count,iPush=count-1;
    stack<int> buf;
    buf.push(*push++);
    while(iPush>0){
        while(!buf.empty() && buf.top()!=*pop){
            buf.push(*push++);
            iPush--;
        }
        while(!buf.empty() && buf.top()==*pop){
            buf.pop();
            iPop--;
            pop++;
        }
    }
    return iPop==0?1:0;
}
第三十题:1到N的整数中出现1的次数
高效的方法太复杂了,低效的方法很简单,就是%10看余数,再除以10.
int helper(int n){
    int k=n;
    int cnt=0;
    while(n!=0){
        if(n%10==1)cnt++;
        n/=10;
    }
    return cnt;
}
 
int countOne(int n){
    int cnt=0;
    for(int i=1;i<=n;++i)cnt+=helper(i);
    return cnt;
}

 

posted @ 2013-03-28 09:34  iyjhabc  阅读(206)  评论(0编辑  收藏  举报