数据结构与算法

1. 红黑树相关问题

  • 能保证在最坏情况下,基本的动态几何操作的时间均为O(lgn)
  • 红黑树的查找效果是有最低保证的。在最坏的情况下也可以保证O(logN)的,这是要好于二叉查找树的。因为二叉查找树最坏情况可以让查找达到O(N)。
  • 如果你的数据分布较好,则比较宜于采用 AVL树(例如随机产生系列数),但是如果你想处理比较杂乱的情况,则红黑树是比较快的

2.常见排序算法总结

算法最好时间最坏时间平均时间额外空间稳定性
选择n2 n2 n2 1不稳定
冒泡nn2 n2 1稳定
插入nn2 n2 1稳定
希尔nn2 n1.3(不确定) 1不稳定
归并nlog2nnlog2nnlog2nn稳定
快排nlog2nn2 nlog2nlog2n至n不稳定
nlog2nnlog2nnlog2n1不稳定
基数n*kn*kn*kn+k稳定

3.对比一下数组和链表的优缺点。

  • 数组:优点是支持随机访问,缺点是插入和删除效率低,内存空间要求高,必须有足够的连续内存空间。
  • 链表:优点是插入删除速度快,内存利用率高,不会浪费内存。缺点是不能随机查找。

4. 两个栈模拟队列怎么实现?

假设有栈A和B,入队就直接进栈A,出队先看B,B不为空就直接栈顶元素出栈,否则先把A的所有元素出栈并进栈到B中,再弹出B的栈顶元素。

5. 如何优化快排使得它稳定?

暂时不想理

6. 快速排序是最快的排序算法吗?

快速排序的时间复杂度是基于比较的排序算法的最低的,也就是O(nlogn),但是特殊情形下是有线性排序的算法的,它们不是基于比较的,主要有计数排序,桶排序和基数排序。其中桶排序是稳定的,是常见排序里最快的一种,但桶排序是有要求的,就是数组元素隶属于固定(有限的)的区间,如范围为[0-9] (考试分数为1-100等)
参考 比较型排序与非比较型排序算法的总结

7. 了解迪杰斯特拉算法吗?作用是什么?描述一下计算步骤。可以求得最优解吗?了解启发式搜索吗?

参考 常用搜索算法—盲目搜索和启发式搜索

8. A星算法?

A星寻路算法-(入门级)

9. 如何评价一个哈希函数的质量?发生冲突如何处理?

评价哈希函数优劣的因素有:

  • 能否将关键字均匀影射到哈希空间上
  • 有无好的解决冲突的方法
  • 计算哈希函数是否简单高效

哈希冲突的解决方法包括:

  • 开放定址法(包括线行探查法,平方探查法等)
  • 链地址法
  • 再哈希法

10. 求top k的几种方法?

答:1)小顶堆的方法:O(nlogK) 的复杂度,如果 K 远小于 n 的话, O(nlogK) 其实就接近于 O(n) 了。优点是需要的内存比较小。
2)快排的 partition 划分:时间复杂度是 O(n),需要内存比较多。
参考 算法必学:经典的 Top K 问题

11.如何判断一个链表是否带环?

快慢指针法,详见《剑指Offer》

12.不使用第三个数交换两个数

void swap(int& a,int& b)  
{  
     a = a^b;  
     b = a^b;  
     a = a^b;  
}  

13.快排最坏情况什么时候出现?如何避免?

这个答案还得看枢轴(pivot)的选择策略。在快速排序的早期版本中呢,最左面或者是最右面的那个元素被选为枢轴,那最坏的情况就会在下面的情况下发生啦:

  • 数组已经是正序(same order)排过序的。
  • 数组已经是倒序排过序的。
  • 所有的元素都相同(1、2的特殊情况)

因为这些案例在用例中十分常见,所以这个问题可以通过要么选择一个随机的枢轴,或者选择一个分区中间的下标作为枢轴,或者(特别是对于相比更长的分区)选择分区的第一个、中间、最后一个元素的中值作为枢轴。有了这些修改,那快排的最差的情况就不那么容易出现了,但是如果输入的数组最大(或者最小元素)被选为枢轴,那最坏的情况就又来了。

14.手写快排

#include<stdio.h>

//交换函数
void swap(int &a, int &b)
{
    int t = a;
    a = b;
    b = t;
}

int partition(int a[], int low, int high)
{
    int x = a[low];    //将该数组第一个元素设置为比较元素
    int i = low;    //指向数组头的指针
    int j = high;    //指向数组尾的指针
    while (i < j)
    {
        while (i < j && a[j] >= x)
            j--;    //从右至左找到第一个小于比较元素的数
        while (i < j && a[i] <= x)
            i++;    //从左至右找到第一个大于比较元素的数
        /*需要注意的是,这里的j--与i++的顺序不可以调换!
          如果调换了顺序,i会走过头,以至于将后面较大的元素交换到数组开头*/

        //将大数与小数交换
        if (i != j)
            swap(a[i], a[j]);
    }
    swap(a[low], a[i]);    //将比较元素交换到期望位置
    return i;    //返回比较元素的位置
}

void quicksort(int a[], int low, int high)
{
    if (low < high)
    {
        int i = partition(a, low, high);    //划分数组并获取比较元素的位置
        quicksort(a, low, i - 1);    //对比较元素左边进行排序
        quicksort(a, i + 1, high);    //对比较元素右边进行排序
    }
}

int main()
{
    int a[] = { 5,7,1,6,4,8,3,2 };
    int length = sizeof(a) / sizeof(a[0]);
    quicksort(a, 0, length - 1);
    for (int i = 0; i < length; i++)
        printf("%d ", a[i]);
    printf("\n");
    return 0;
}

15. 图的存储方式

1、邻接矩阵(数组)
2、邻接表(链表)
3、邻接多重表(链表)
4、十字链表(链表)
参考 数据结构—图的存储方式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值