2020腾讯实习生招聘面试算法题

这篇博客分享了2020年腾讯实习生招聘面试中遇到的三道算法题,包括堆排序的实现、快速幂求幂操作以及单链表的反转方法。通过代码展示了解题思路,强调面试中快速解决问题的重要性,提示需要加强算法练习。

主要是从同学这打听到的,于是自己也写了一下。第一道就是叫手写一个堆排序,第二道是写幂,第三道链表反转。

堆排序

 堆排序其实就是叫建堆嘛,最大堆和最小堆,之前也写过,具体见 堆和堆排序。这次写的时候写成了模板,想着要好点。

#include <iostream>
#include <algorithm>
using namespace std;

// 两个比较仿函数,STL有自带的,也可用自带的 greater 和 less
template<typename type>
struct mgreater{
    bool operator()(const type& a, const type& b){return a>b;}
};

template<typename type>
struct msmaller{
    bool operator()(const type& a, const type& b){return a<b;}
};

template<typename type, typename COMP>
class heap{
private:
    type *heaptop;    // 用数组存储,来构建堆
    int len;        // 存储堆大小
    COMP comp;    
public:
    heap(int length){
        heaptop = new type[length];     // 预分配堆大小
        len = 0;
    }
    ~heap(){ delete [] heaptop;}           // 释放堆

    void insertNode(type nums){         // 新节点插入
        if(0==len) {                    // 堆为空,即直接插入,无需上调
            heaptop[len++] = nums;
            return;
        }
        int cur = len++;                // 插入新节点,放入末尾,并进行上调
        heaptop[cur] = nums;
        while(cur>0){
            if(comp(heaptop[cur], heaptop[(cur-1)/2])) break; 
            // 当前节点和父节点比较,父节点满足和子节点的comp,则交换
            swap(heaptop[cur], heaptop[(cur-1)/2]);
            cur = (cur-1)/2;                                    
        }
    }

    type gettop(){        // 仅返回堆顶点,不执行删除
        if(len<=0) return -1;
        return heaptop[0];
    }

    int getLen(){ return len;}    //返回堆大小

    type removeNode(){    //删除堆顶点,并返回堆顶元素
        if(len<=0) return static_cast<type>(-1);
        swap(heaptop[0], heaptop[--len]);   // 将堆顶元素和末尾元素交换,堆大小-1,实现假删除
        int cur = 0;
        int child = (cur+1)*2;    // 右孩子位置
        while(child<len){
        /**
        ** 这里需要跟插入时比对好,选择一个和父节点进行交换,因为此时的父节点是从末尾交换而来,
        ** 所以一定是可以下沉的
        **/
            if(comp(heaptop[child], heaptop[child-1])){ 
                swap(heaptop[child-1], heaptop[cur]);
                cur = child - 1;
            } else {
                swap(heaptop[child], heaptop[cur]);
                cur = child;
            }
            child = (cur+1)*2;
        }
        // 跳出循环,可能只有一个左孩子节点,做最后的分析
        if(child-1<len && comp(heaptop[cur], heaptop[child-1]))
            swap(heaptop[cur], heaptop[child-1]);
        return heaptop[len];
    }
};

int main()
{
    int a[10] = {3,2,3,4,1,6,7,19,10,8};
//    priority_queue<int, vector<int>, greater<int>> mm;

    heap<int, mgreater<int>> hh(10);
    for(int i=0;i<10;i++){
        hh.insertNode(a[i]);
    }
    cout <<"size: " <<hh.getLen() <<endl;
    while(hh.getLen()>0){
        cout <<hh.removeNode() <<" ";
    }
    cout <<endl;
    return 0;
}

求幂

求幂那就再经典不过了,快速幂,思想就是利用幂的特性,实现底数的快速翻倍,从而达到幂的指数增长。直接上代码了

#include <iostream>
using namespace std;

// 快速幂的思想就是利用 将底数翻倍的思想来达到 幂的指数增长
int quickm(int m, int n)
{
    if(1==m || 0==n) return 1;
    else if(1==n) return m;
    long long res = 1;    // 结果用long long 存储
    while(n){
        if(n&1) res*=m;
        m*=m;
        n>>=1;
    }
    return res;
}

int main()
{
    cout <<"2, 8:  " <<quickm(2,8) <<endl;
    cout <<"10, 3: " <<quickm(10,3) <<endl;
    cout <<"1, 99: " <<quickm(1,99) <<endl;
    cout <<"2, 20: " <<quickm(2,20) <<endl;
    return 0;
}

单链表反转

链表反转也是比较常问的题目,一般的方法就是双指针的方法,还有一个呢就是想法比较质朴的,额外数组存储,另起一个链表。我自己使用双指针来写的,直接上代码:

#include <iostream>
using namespace std;

struct node{
    int value;
    node* next;
    node(int val){
        value = val;
        next = NULL;
    }
};

void printLink(node *head)
{    //链表打印
    node *tem = head;
    while(tem!=NULL){
        cout <<tem->value <<" ";
        tem = tem->next;
    }
    cout <<endl;
}

node* reverseLink(node *head)
{
    if(head==NULL || head->next==NULL) return head;
    // 就是一个记录head 节点的前驱,一个记录后驱,加上head本身,三个节点
    node *p1 = NULL, *p2 = head->next; 
    while(p2!=NULL){
        head->next = p1;
        p1 = head;
        head = p2;
        p2 = p2->next;
    }
    head->next = p1;
    return head;
}

int main()
{
    int a[10] = {1, 2,3,4,5,6,7,8,9,10};
    node *head = new node(1);
    node *tem = head;
    for(int i=1;i<10;i++){
        tem->next = new node(a[i]);
        tem = tem->next;
    }
    printLink(head);

    head = reverseLink(head);
    printLink(head);
    return 0;
}

虽然都不太难,但是在面试的情况下,叫我现场手写还是达不到很快就能写出来的地步。确实还是要加强练习啊,像有同学面试的时候三分钟手写快排,已经惊呆了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值