已理解的题

关于树的深度优先搜索算法描述错误的是

A : 按照某个条件往前试探搜索,如果前进中遭遇失败, 则退回头另选通路继续搜索,直到找到条件目标为止
B: 先访问该节点所有的子节点, 遍历完毕后选取它未访问过的子节点重复上述过程,直到找到条件目标为止
C: 假设树的顶点树为V,则算法的空间复杂度为O(V)
D: 深度优先算法非常适合使用递归来实现

对于C选项来说,我不是太理解,因为DFS,空间复杂度就是树递归的深度, 那么就是logH,除非是树退化为链表的情况才是空间复杂度为O(V)啊

,因为DFS,空间复杂度就是树递归的深度, 那么就是logH,除非是树退化为链表的情况才是空间复杂度为O(V)啊

将10阶对称矩阵压缩存储到一维数组A中,则数组A的长度最少是多少

在这里插入图片描述
比如5阶的为5 * 5 / 2 + 对角线的另一半 (5 / 2) = 12.5 + 2.5 = 15个长度
所以10阶的为10 * 10 / 2 + 10 / 2 = 50 + 5 = 55

需要频繁的插入和删除操作使用数组,队列,链表,栈这四种数据结构中的 链表最合适,如果只考虑只在最后一个位置频繁删除和插入那么栈,链表都可以
已知循环队列存储在一维数组A[0…n-1]中,且队列非空时front和rear分别指向队头和队尾元素, 若初始队列为空,且要求第1个进入队列的元素存储在A[0]处,则初始时front和rear的值分别是0和n - 1

循环队列需要留出一个空间,方便判断队列是否为满(循环队列解决假溢出);
常用的队列实现:
当队列为空时,front == rear;其中rear指向队尾元素的下一个位置,即下一个元素入队的位置
入队操作:先赋值,再rear = (rear+1)%MAXSIZE;此时rear仍然指向队尾元素的下一个位置

但是题目中!!!有一句!!!front和rear分别指向队头元素和队尾元素!!!
rear指向队尾元素!!!
把常用的队列实现方法来了个886
那么,在这道题中,判断队满和队空我是一时半会想不下去了。。。(front == (rear + 1)%MAXSIZE 既可以是满,也可以是空啊= =,除非说还要留一个空间出来)

但是!!!
这道题说,初始时队列为空,无论如何还是front == (rear + 1)%MAXSIZE.

简单的说就是,队列是空的,rear指向队尾元素,front指向队头元素,入队了,(rear +1)%n,这个时候A[0]既是队头元素,也是队尾元素,rear = front = 0;所以是rear = n-1

在一个长度为n的顺序表中删除第i元素 ,要移动n - i个元素, 如果要在第i个元素前插入一个元素,要后移 n - i + 1

这里注意第i个元素不包含第0个元素,因为我们想到的是数组从0下标开始,实际计算的时候 第0个下标在第1个元素的位置

二叉树的先序遍历为EFHIGJK 和中序遍历 HFIEJKG, 则二叉树为

                E

       F                    G

   H      I           J
	                     K

第二次考试题
解码方程

dp[i]为str[0…i]的译码方法总数
分情况讨论
1若s[i] = ‘0’ ,那么若s[i-1] = '1’或者’2’则pd[i] = dp[i-2],否则为0
2若s[i-1] = ‘1’,则dp[i] = dp[i-1] + dp[i-2]
解释:s[i-1]和s[i]分开译码,为dp[i-1],合并译码为dp[i-2]
3若s[i-1] = ‘2’ and ‘1’ <=s[i] <=“6”,则dp[i] = dp[i-1] + dp[i-2]
因为dp[i]只和前两项有关,可以单变量单体dp[]数组
将空间复杂度从O(n)降低到O(1)
Decode Ways
1.算法思路
动态规划求解
这道题的分类非常重要
若s[i]=‘0’,则
若s[i-1]='1’或‘2’,则dp[i]=dp[i-2]
否则不存在,无解
若s[i]='1’则dp[i]=dp[i-1]+dp[i-2]
因为这样会增加两种译码方法
一个是合在一起,也就是dp[i-2]
一个是分开译码,就是dp[i-1]
若s[i-1]=‘2’,并且s[i]在1~6之间,则同上dp[i]=dp[i-1]+dp[i-2]
因为dp[i]只和前两项有关,则我们使用单个变量代替创建整个dp数组就可以把空间复杂度从O(N)变为O(1)

    func numDecodings(_ s: String) -> Int {
         let len = s.count
         if len == 0 || s[0] == "0" {return 0}
         var pre = 1, cur = 1
         for i in 1..<len { // 注意:// 这样写是错误的,越界 for i in 2..<len + 1 {
             let temp = cur
             if s[i] == "0" {
                 if s[i-1] == "1" || s[i-1] == "2" {
                     cur = pre
                 }else{
                     return 0
                 }
             }else if s[i-1] == "1" || (s[i-1] == "2" && s[i] >= "1" && s[i] <= "6") {
                 cur = cur + pre
             }
             pre = temp
         }
         return cur
     }
   public int numDecodings(String s) {
	    int n = s.length();
        if (n == 0 || s.charAt(0) == '0')     return 0;
        int[] dp = new int [n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i < n + 1; ++i) {
            if (s.charAt(i - 2) == '1' || s.charAt(i - 2) == '2' && s.charAt(i - 1) <= '6')
                dp[i] += dp[i - 2];
            if (s.charAt(i - 1) != '0')
                dp[i] += dp[i - 1]; 
        }
        return dp[n];
    }

单词接龙

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
  // 先将 wordList 放到哈希表里,便于判断某个单词是否在 wordList 里
        Set<String> wordSet = new HashSet<>(wordList);
        if (wordSet.size() == 0 || !wordSet.contains(endWord)) {
            return 0;
        }

        // 标准写法,总的 visited 数组
        Set<String> visited = new HashSet<>();

        // 分别用左边和右边扩散的哈希表代替单向 BFS 里的队列
        Set<String> beginVisited = new HashSet<>();
        beginVisited.add(beginWord);

        Set<String> endVisited = new HashSet<>();
        endVisited.add(endWord);

        int len = beginWord.length();
        int step = 1;
        while (!beginVisited.isEmpty() && !endVisited.isEmpty()) {
            // 打开以方便调试
            // System.out.println("beginVisited => " + beginVisited);
            // System.out.println("  endVisited => " + endVisited + "\n");

            // 优先选择小的哈希表进行扩散,考虑到的情况更少
            if (beginVisited.size() > endVisited.size()) {
                Set<String> temp = beginVisited;
                beginVisited = endVisited;
                endVisited = temp;
            }

            // 逻辑到这里,保证 beginVisited 是相对较小的集合
            // nextLevelVisited 在扩散完成以后,会成为新的 beginVisited
            Set<String> nextLevelVisited = new HashSet<>();
            for (String word : beginVisited) {
                char[] charArray = word.toCharArray();
                for (int i = 0; i < len; i++) {
                    char originChar = charArray[i];
                    for (char c = 'a'; c <= 'z'; c++) {
                        if (originChar == c) {
                            continue;
                        }
                        charArray[i] = c;
                        String nextWord = String.valueOf(charArray);
                        if (wordSet.contains(nextWord)) {
                            if (endVisited.contains(nextWord)) {
                                return step + 1;
                            }
                            if (!visited.contains(nextWord)) {
                                nextLevelVisited.add(nextWord);
                                visited.add(nextWord);
                            }
                        }
                    }
                    // 恢复,下次再用
                    charArray[i] = originChar;
                }
            }

            // 这一行代表表示从 begin 这一侧向外扩散了一层
            beginVisited = nextLevelVisited;
            step++;
        }
        return 0;
    }
    
    public static void main(String[] args) {
        List<String> wordList = new ArrayList<>();
        String[] words = {"hot", "dot", "dog", "lot", "log", "cog"};
        Collections.addAll(wordList, words);

        Solution solution = new Solution();
        String beginWord = "hit";
        String endWord = "cog";
        int ladderLength = solution.ladderLength(beginWord, endWord, wordList);
        System.out.println(String.format("从 %s 到 %s 的最短转换序列的长度:%d。", beginWord, endWord, ladderLength));
    }

}

简答题

下列叙述中正确的是
A.线性链表中的各元素在存储空间中的位置必须是连续的
B.线性链表中的表头元素一定存储在其他元素的前面
C.线性链表中的各元素在存储空间中的位置不一定是连续的,但表头元素一定存储在其他元素的前面
D.线性链表中的各元素在存储空间中的位置不一定是连续的,且各元素的存储顺序也是任意的
正确答案:D
解析:性表的链式存储结构中,各数据结点的存储序号不连续,且各结点在存储空间中的位置关系与逻辑关系也不一致。性链表中,各数据元素之间的前后件关系是由各结点的指针域来指示的。所以,选项D正确。

将 A B C D 四个元素次序进栈(中间可能有出栈操作,例如 A 进栈后出栈,B 再进栈),则可能的出栈系列是
C A D B
B D C A
C D A B
D A B C
B为什么对。 A先压进去,再压入B,然后把B弹出来,所以B最先出栈。 然后把C压入栈,D再压入栈,根据先进先出原则依次弹出,所以剩下的三个数字出栈顺序为D,C,A。 所以总顺序为B,D,C,A
红黑树性质
1.每个结点要么是红的要么是黑的。
2.根结点是黑的。
3.每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。
4.如果一个结点是红的,那么它的两个儿子都是黑的。
5.对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。

布隆过滤器的定义和特性
一个很长的二进制向量和一系列随机映射函数.布隆过滤器可以用于检索一个元素是否在一个集合中
优点是空间效率和查询时间都远远超过一般的算法(模糊查询)
缺点是有一定的误识别率和删除困难

在最坏的情况下,下列排序方法中时间复杂度最小的是: 对长度为n的线性表排序,冒泡排序、快速排序、直接插入排序的时间复杂度均为O(n^2),堆排序时间复杂度为O(nlogn),复杂度最小。

设一棵完全二叉树共有699个结点,则在该二叉树中的叶子结点数为多少个。
完全二叉树中如果全部节点数为奇数,说明含度为1的节点;设叶子节点数为no,度为2的节点数为n2,则有n0=n2+1;
2*n0 -1 = 699; n0=350
按从1到699编号,最后一个是699号,也就是最后一个叶子节点,设其对应的父节点为n,2n+1=699,n=349,其父节点是最后一个非叶子节点,所以叶子节点数为699-349=350
下列哪两个数据结构,同时具有较高的查找和删除性能?()
有序数组
有序链表
AVL树
Hash表
解析:几种常见的数据结构的操作, 平衡二叉树的查找,插入和删除性能都是O(logN),其中查找和删除性能较好;哈希表的查找、插入和删除性能都是O(1),都是最好的。
下面关于哈希查找的说法中,正确的是( )
哈希函数构造的越复杂越好,因为这样随机性好,冲突小
除留余数法是所有哈希函数中最好的
不存在特别好与坏的哈希函数,要视情况而定
若采用开放定址法处理冲突,则删除元素只需直接将该元素从哈希表中删去即可
答案:c 哈希函数都要视情况而选择,比如填装因子不同,表长变化,在哈希法时的哈希函数都不同。

已知一个二叉树前序遍历结果ABCDEFGH和中序遍历结果CDBAGFEH

/*
              A
      B             E
C             F        H
   D      G   
*/

那么后续为DCBGFHEA

一个数组长度为n。指定数组内的一个元素,把数组内小等于该元素的,放在该元素左边,把数组内大于该元素的,放在该元素右边。这个需要多少次操作

在N个乱序数字中查找第K大的数字

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值