《牛客》做题阶段二错题总结(一)

前言

  牛客第一阶段选择题做了2300多道了,现在考虑放慢做题速度,开始着重总结和公司真题及失缺知识点的补充,以下是阶段性记录吧:
这里写图片描述

1. 二叉树相关

问题:设只含根节点的二叉树高度为1,现有一颗高度为h(h>1)的二叉树上只有出度为0和出度为2的结点,则此二叉树中所包含的结点数至少为__个。

  陷阱是会想到必须是完全树或者满树,但是实际上以如下图的所示的方式生成树:
这里写图片描述

2. 集合和线性表

问题:集合与线性表的区别在于是否按关键字排序()

  集合的特点为:确定性、互异性、无序性。而线性表的基本特征为:存在唯一的“第一个元素”、存在唯一的“最后一个元素”、除最后一个元素之外均有唯一后继、除第一个元素外均有唯一前驱。

3.STL Set补充

Container properties:

  • Associative
    • Elements in associative containers are referenced by their key and not by their absolute position in the container.位置无关,只和key相关
  • Ordered
    • The elements in the container follow a strict order at all times. All inserted elements are given a position in this order.有序,当然这种有序是因为红黑树的底层数据结构
  • Set
    • The value of an element is also the key used to identify it.元素的值也就是key
  • Unique keys
    • No two elements in the container can have equivalent keys.不重复
  • Allocator-aware
    • The container uses an allocator object to dynamically handle its storage needs.

The value of the elements in a set cannot be modified once in the container (the elements are always const), but they can be inserted or removed from the container.

  Set中的值不能直接被改变,但可以删除或者插入。

4. KMP算法相关

问题:串′ababaaababaa′的next数组为()

  回顾之前记录篇算法补充之KMP作用原理(一),直接看伪代码:

//未优化的版本,伪代码:
algorithm kmp_table:
    input:
        an array of characters, W (the word to be analyzed)
        an array of integers, T (the table to be filled)
    output:
        nothing (but during operation, it populates the table)

    define variables:
        an integer, pos ← 2 (the current position we are computing in T)
        an integer, cnd ← 0 (the zero-based index in W of the next 
character of the current candidate substring)

    (the first few values are fixed but different from what the algorithm 
might suggest)
    let T[0] ← -1, T[1] ← 0
    //pos从2开始,所以刚开始的判断为w[1],w[0],cnd=0 注意cnd代表了当前substring的最长前缀的下一个值。
    while pos < length(W) do
        (first case: the substring continues)
        if W[pos - 1] = W[cnd] then
            let cnd ← cnd + 1, T[pos] ← cnd, pos ← pos + 1
        //如果没有拓展这个最长前缀,按照上面的算法我们应该以--cnd>=0的方式检查
        //但是这样会判断多余的长度,采用cnd=T[cnd]避免检查没有必要的最长前缀长度
        (second case: it does not, but we can fall back)
        else if cnd > 0 then
            let cnd ← T[cnd]
        //第三种情况,从T[pos-1]的cnd值直到0都检查过了,没有符合要求的前后缀,则此时设置T[pos]=0;
        (third case: we have run out of candidates.  Note cnd = 0)
        else
            let T[pos] ← 0, pos ← pos + 1

  按照伪代码的逻辑进行匹配表的构建:

i 0 1 2 3 4 5 6 7 8 9 10 11
W[i] a b a b a a a b a b a a
T[i] -1 0 0 1 2 3 1 1 2 3 4 5

  在写代码的时候,为了提高效率,优化成let cnd ← T[cnd]。人工建表的时候,其实--cnd>0的方式更快。

5. 快速排序

问题:对n个记录的线性表进行快速排序为减少算法的递归深度,以下叙述正确的是()

  一些快排的实现与《数据结构与算法分析》不同,后者有三项划分中项或者五划分中项的中项的优化做法。这在之前的记录篇都有涉及DSAA之快速排序(一),但是在牛客或者一些国内教材,快排的实现遵照以下过程,以下来自百度百科:

一趟快速排序的算法是:

  • 设置两个变量i、j,排序开始的时候:i=0,j=N-1;
  • 以第一个数组元素作为关键数据,赋值给key,即key=A[0];
  • 从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]互换;
  • 从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
  • 重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

  重新回到原问题中,在分治策略中,如果先处理长度较短的部分,将减少递归深度。这可以通过画分支树来观察,这里可以当结论记住。

6. 迭代器失效问题

  首先BYR_jiandong作者总结的很到位,以下引用来自该博友:

  • 数组型数据结构:该数据结构的元素是分配在连续的内存中,insert和erase操作,都会使得删除点和插入点之后的元素挪位置,所以,插入点和删除掉之后的迭代器全部失效,也就是说insert(*iter)(或erase(*iter)),然后在iter++,是没有意义的。解决方法:erase(*iter)的返回值是下一个有效迭代器的值。 iter =cont.erase(iter);
  • 链表型数据结构:对于list型的数据结构,使用了不连续分配的内存,删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器.解决办法两种,erase(*iter)会返回下一个有效迭代器的值,或者erase(iter++).
  • 树形数据结构: 使用红黑树来存储数据,插入不会使得任何迭代器失效;删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器.erase迭代器只是被删元素的迭代器失效,但是返回值为void,所以要采用erase(iter++)的方式删除迭代器。

  针对每种,我特意整理cplusplus权威网站的解释,分别查看vector,List,map三种结构:

  • Vector
    • erase:Otherwise, only those pointing to position and beyond are invalidated, with all iterators, pointers and references to elements before position guaranteed to keep referring to the same elements they were referring to before the call.当前位置和之后的迭代器失效
    • push_back:Otherwise, only the end iterator is invalidated, and all iterators, pointers and references to elements are guaranteed to keep referring to the same elements they were referring to before the call.只有最后的迭代器失效
    • insert:Otherwise, only those pointing to position and beyond are invalidated, with all iterators, pointers and references to elements before position guaranteed to keep referring to the same elements they were referring to before the call.插入点和之后的迭代器失效
  • List
    • insert:No changes.
    • erase: Iterators, pointers and references referring to elements removed by the function are invalidated. All other iterators, pointers and references keep their validity.
  • Map
    • insert:No changes.
    • erase:Iterators, pointers and references referring to elements removed by the function are invalidated. All other iterators, pointers and references keep their validity.

猜你喜欢

转载自blog.csdn.net/lovestackover/article/details/80934009