挑战数据结构与算法面试题——80题全解析(一)

来源:互联网 发布:java redis缓存用法 编辑:程序博客网 时间:2024/06/11 06:31

题目来源“数据结构与算法面试题80道”。这是第一部分,包含其中的第1题到第5题。
在此给出我的解法,如你有更好的解法,欢迎留言。

这里写图片描述

问题分析:二叉查找树是一种二叉树的结构,其中,根节点的值大于左子树的值,小于右子树的值。而二叉查找树的中序遍历即为排序的结果。对于根节点,前驱指针指向左子树中最大的节点,同理,后驱指针指向右子树中最小的节点,如下图所示:

这里写图片描述

树是一种递归的结果,因此,对于左右子树,也需要执行相同的操作。

方法:

BSTreeNode* convert(BSTreeNode *root){    if (NULL == root ||        (NULL == root->m_pLeft && NULL == root->m_pRight)){        return root;    }    convert(root->m_pLeft);    BSTreeNode* p_left = root->m_pLeft;    while(p_left->m_pRight != NULL){        p_left = p_left->m_pRight;    }    root->m_pLeft = p_left;    p_left->m_pRight = root;    convert(root->m_pRight);    BSTreeNode* p_right = root->m_pRight;    while(p_right->m_pLeft != NULL){        p_right = p_right->m_pLeft;    }    root->m_pRight = p_right;    p_right->m_pLeft = root;    BSTreeNode *p = root;    while (NULL != p->m_pLeft){        p = p->m_pLeft;    }    return p;}

这里写图片描述

问题分析:栈的特点是先进后出。要能够取出当前的最小值,需要用另一个栈保存当前的最小值,所以可采用“双栈”的结构,一个栈保存所有的值,另一个栈保存当前的最小值。

方法:

template <class Type> class min_stack{    private:        stack<Type> s1;        stack<Type> s2;    public:        min_stack(){}        ~min_stack(){}        Type min(){            if (!s2.empty()){                return s2.top();            }        }        void push(Type a){            s1.push(a);            if (s2.empty() || a <= s2.top()){                s2.push(a);            }        }        Type pop(){            if (!s1.empty() && !s2.empty()){// 非空                if (s1.top() == s2.top()){                    s2.pop();                }                return s1.pop();            }        }};

这里写图片描述

问题分析:在数组的每一个位置处保存当前的最大值,当前的最大值组成为:

f(xi)={xif(xi1)+xi if i=0orf(xi1)0 if f(xi1)>0

解决方案:

int get_max_subarray(int *a, int length, bool &is_array_ok){    if (NULL == a || length <= 0){        is_array_ok = false;        return 0;    }    int *p_h_a = (int *)malloc(sizeof(int) * length);    // 遍历数组    int max_num = 0;    for (int i = 0; i < length; i++){        if (i == 0 || (i > 0 && p_h_a[i-1] <= 0)){            p_h_a[i] = a[i];        }else{            p_h_a[i] = p_h_a[i-1] + a[i];        }        if (max_num < p_h_a[i]) max_num = p_h_a[i];    }    free(p_h_a);    is_array_ok = true;    return max_num;}

这里写图片描述

问题分析:核心是树的遍历,注意题目中“路径”的定义,是从根节点到叶子节点。先序遍历正好是从根节点开始,因此可以利用先序遍历的过程来实现这个过程。

方法:

void print_vector(vector<BinaryTreeNode *> &v){    vector<BinaryTreeNode *>::iterator it;    for (it = v.begin(); it != v.end(); it ++){        printf("%d\t", (*it)->m_nValue);    }    printf("\n");}void pre_order_route(BinaryTreeNode *p, int num, vector<BinaryTreeNode *> &q, int &current){    if (NULL == p) return;    current += p->m_nValue;    q.push_back(p);    bool is_leaf = (NULL == p->m_pLeft) && (NULL == p->m_pRight);    if (current == num && is_leaf){        print_vector(q);    }    if (NULL != p->m_pLeft){        pre_order_route(p->m_pLeft, num, q, current);    }    if (NULL != p->m_pRight){        pre_order_route(p->m_pRight, num, q, current);    }    current -= (*(q.end() - 1))->m_nValue;    q.pop_back();}void print_route(BinaryTreeNode *root, int num){    vector<BinaryTreeNode *> q;// 用队列保存已经访问过的节点    int current = 0;    pre_order_route(root, num, q, current);}

这里写图片描述

问题分析:这是一道比较经典的题目,查找最小的k个元素,最简单的方法就是对这n个整数排序,排序完成后,直接输出前k个最小的元素。那么最快的排序方法是快速排序,其算法的时间复杂度为O(nlogn)。是否还存在比这个更快的方法呢?

方法一:利用快速排序的思想,时间复杂度为O(n)

按照某个点将数组划分成左右两部分,左边的数都小于该划分节点,右边的数都大于该划分节点。如果最终该划分节点的位置小于k-1,则在右边节点中继续划分;如果最终该划分节点的位置大于k-1,则在左边节点中继续划分。这个过程直到最终的划分节点的位置正好为k-1。

int swap(int *a, int start, int end, int point_index){    int par_point = a[point_index];    while (start < end){        if (a[start] >= par_point && a[end] <= par_point){            int tmp = a[start];            a[start] = a[end];            a[end] = tmp;            start ++;            end --;        }else if(a[start] < par_point){            start ++;        }else{            end --;        }    }    return start;}void get_min_k(int *a, int length, int k){    if (k > length || NULL == a || length <= 0) return;    int new_index = swap(a, 0, length-1, k);    while (true){        if (new_index == k) break;        else if (new_index > k){            new_index = swap(a, 0, new_index, k);        }else{            new_index = swap(a, new_index, length-1, k);        }    }}

方法二:利用堆排序,时间复杂度为O(nlogk)

上述方法的缺点是其对数组进行了修改,在堆排序中,可采用小顶堆,其中堆的大小为k,若此时堆的大小小于k时,则将数插入堆中;若此时堆中的大小大于等于k,则比较堆中最大的整数与待插入整数的大小,插入较小的整数。

void get_min_k(int *a, int length, int k, set<int> &s){    if (k > length || NULL == a || length <= 0) return;    for (int i = 0; i < length; i++){        if (s.size() < k){            s.insert(a[i]);        }else{            set<int>::iterator it = --s.end();            if (a[i] < *it){                s.erase(*it);                s.insert(a[i]);            }        }    }}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买房子把办贷款的单据丢了怎么办 鞋盒破损卖家拒绝退货怎么办 顺丰快递退回发件人签收失败怎么办 客户收到衣服后说衣服破损怎么办 纱窗被老鼠咬了个洞怎么办 双色印刷机开槽刀调不动怎么办 水管软管两端的螺帽下包生锈怎么办 棉花被子盖时间长了被芯变小怎么办 垫的被子发霉了啊没有地方晒怎么办 小孩拉尿在丝棉被棉怎么办 把兔子养大了竟然会咬人怎么办 小兔子生下来母兔子不喂奶怎么办 11个月的宝宝肚子有小白虫怎么办 电焊把脸烤了痒的不行怎么办? 还没满月的宝宝吐奶怎么办 周岁宝宝发烧腹泻吃药老吐怎么办 生完宝宝后肚皮很黑怎么办 两个月宝宝抵抗力差总生病怎么办 两岁宝宝只会说几个简单的词怎么办 两岁宝宝对绘本不感兴趣怎么办 一岁十个月宝宝不爱吃饭怎么办 孩子上三年级学习太差应该怎么办 mac系统打数字出显符号怎么办 我太粗心了工作中总犯错怎么办 四年级的孩子数学计算总粗心怎么办 小孩做作业拖拉的很厉害怎么办 二年级孩子做作业太粗心怎么办 发现孩子做作业时玩手机怎么办 高三孩子考试时慌乱老粗心怎么办 助班面试你的学生不喜欢你怎么办 上三年级的小孩不愿做作业怎么办 快一年了孩子上幼儿园总哭怎么办 宝宝吃多了吐了很多怎么办 一岁宝宝只吃母乳不吃辅食怎么办 孩子平常考得好正式考不好怎么办 平常成绩好期末却考不好怎么办 初中生去国外上学国内的学校怎么办 孩子在学校不受老师的重视怎么办 孩子上二年级了不爱学习怎么办 接别人的班被学生讨厌怎么办 孩子在学校老师打孩子家长怎么办?