算法常见面试问题

常用排序

堆排序

void heapAdjust(vector<int>&v,int parent,int length){
    for (int j = parent*2; j <=length; j*=2) {
        if(j+1<=length && v[j+1]>v[j])
            j++;
        if(v[parent]>v[j])
            break;
        swap(v[parent],v[j]);
        parent=j;
    }
}
void heapSort(vector<int>&v){
    for(int i=(v.size()-1)/2;i>=1;--i){   //1
        heapAdjust(v,i,v.size()-1);
    }
    for(int i=v.size()-1;i>=2;i--){
        swap(v[1],v[i]);
        heapAdjust(v,1,i-1);
    }
}

注意点:
1. 其实是用数组存储二叉树,所以,为了方便计算下标,0位置弃用,从1位置开始。不然第一个时,0,其儿子不满足0*2,0*2+1规律。
2. //1 处v.size()-1为最后一个数的下标,除2得到最后一个数的父亲
3. //2处,前面只是j<=m,并没有约束j+1,而//2 &&后面的比较用到j+1,所以必须限制j+1<=m
4. stl中有专门函数可以实现,make_heap,push_heap,pop_heap,sort_heap,

归并排序

递归写法

void merge(vector<int>&srVect,int start,int end,int mid){
    vector<int>tmpVect;
    int i=start,j=mid+1;
    while(i<=mid && j<=end){
        if(srVect[i]<srVect[j])
            tmpVect.push_back(srVect[i++]);
        else
            tmpVect.push_back(srVect[j++]);

    }
    while(i<=mid)
        tmpVect.push_back(srVect[i++]);
    while(j<=end)
        tmpVect.push_back(srVect[j++]);
    copy(tmpVect.begin(),tmpVect.end(),srVect.begin()+start);
}
void mergeSort(vector<int>&srVect,int start,int end){
    if(start<end){
        int mid=(start+end)>>1;
        mergeSort(srVetc,start,mid);
        mergerSort(srVect,mid+1,end);
        merge(srVetc,start,end,mid);
    }
}

非递归写法

void mergePass(vector<int>&srVect,int length){
    int index=0;
    while(srVect.size()-index>=length*2){
        merge(srVect,index,index+length*2-1,index+length-1);
    }
    if(srVect.size()-index>length)//剩下个数介于length,2*length
        merge(srVect,index,srVect.size()-1,index+length-1);
}
void mergeSort2(vector<int>&srVect){
    int length=1;
    while(length<srVect.size()){
        mergePass()
        length*=2;
    }
}

快速排序

int partition(vector<int>&srVect,int left,int right){
    int pivotKey=srVectp[left];
    while(left<right){
        while(left<right && srVect[right]>=pivotKey)  //因为while里面还会对right--,所以还要保证减减后,left<right
            right--;
        swap(srVect[left],srVect[right]);
        while(left<right && srVect[left]<=pivotKey)
            left++;
        swap(srVect[left],srVect[right]);
    }
    return left;
}
void quickSort(vector<int>&srVect,int left,int right){
    if(left<right){                                   //排序至少要两个数
        int index=partition(srVect,left,right);
        quickSort(srVect,left,index-1);               //index已经排好了,所以不用排index
        quickSort(srVect,index+1,right);
    }
}

算法复杂度,用主定理:

冒泡排序

void bubbleSort(vector<int>&srVect){
    for(int i=0;i<srVect.size()-1;++i){
        for(int j=0;j<srVect.size()-i-1;++j){
            if(srVect[j]>srVect[j+1])
                swap(srVect[j],srVect[j+1]);
        }
    }

}

二分查找

int binarySearch(vector<int>&srVect,int val){
    int left=0,right=srVect.size()-1;
    while(left<=right){
        int mid=(left+right)>>1;
        if(srVect[mid]==val)return mid;
        else if(srVect[mid]>val)
            right=mid-1;
        else
            left=mid+1;
    }
    return -1;
}

kmp算法

int* findNext(char*patternStr){
    int*next=(int*)malloc(strlen(patternStr);
    int k=-1,j=0;
    next[0]=-1;
    while(j<strlen(patternStr)){
        if(k==-1 || patternStr[k]==patternStr[j]){
            ++k;
            ++j;
            next[j]=k;
        }
        else
            k=next[k];
    }
}
void kmpSearch(char *srStr,char*patternStr ){
    int slen=strlen(srStr),plen=strlen(patternStr);
    int i=0,j=0;

    while(i<slen && j<plen){
        if(j==-1 || srStr[i]==patternStr[j]){
            ++i;
            ++j;
        }
        else{
            j=next[j];
        }
    }
    if(j==plen)
        return i-plen;
    else 
        return -1;
}

strcpy,memcpy,memmove

char* strcpy(char*dst,char*src){
    if(dst==NULL || src==NULL)return NULL;
    char*tmp=dst;
    while(*src!=0)
        *dst++=*src++;
    *dst=0;
    return tmp;
}
void* memcpy(void*dst,void*src,size_t count){
    if(dst==NULL || src==NULL)return NULL;
    char*pdst=(char*)dst;
    char*psrc=(char*)scr;
    while(count>0){
        *pdst++=*src++;
        --count;
    }
    return dst;
}
void* memmove(void*dst,void*src,size_t count){
    if(dst==NULL || src==NULL)return NULL;
    char*pdst=(char*)dst;
    char*psrc=(char*)scr;
    if(pdst<=psrc || pdst>psrc+count){ //forward copy
        while(count>0){
            *pdst++=*psrc++;
            --count;//count要记得减少
        }
    }
    else{
        while(count>0){
            *(pdst+count)=*(psrc+count);
            --count;
        }
    }
    return dst;
}

注意点

  1. strcpy要考虑最后的’\0’,
  2. memmove要考虑覆盖问题,当pdst不在psrc的范围内,即pdst<=psrc || pdst>psrc+count,用前向拷贝
  3. memcpy,memmove第三个参数要是size_t
  4. strcpy,memcpy,memmove要记得先判断指针不为NULL
点赞