Skip to content

Latest commit

 

History

History
273 lines (209 loc) · 10.5 KB

DataStructureNote.md

File metadata and controls

273 lines (209 loc) · 10.5 KB
数据结构 变种 相关题目 讲解文章
顺序线性表:向量 Vector
栈和队列 Stack & Queue 1. 广义表 Generalized List/GList
2. 双端队列 Deque
队列 Queue 1. 链表实现 Linked List Implementation
2. 循环数组实现 ArrayQueue
3. 双端队列 Deque
4. 优先队列 Priority Queue
5. 循环队列 Circular Queue
单链表 Singly Linked List 1. 双向链表 Double Linked Lists
2. 静态链表 Static List
3. 对称矩阵 Symmetric Matrix
4. 稀疏矩阵 Sparse Matrix
哈希表 Hash Table 1. 散列函数 Hash Function
2. 解决碰撞/填充因子 Collision Resolution
字符串 String 1. KMP 算法
2. 有限状态自动机
3. 模式匹配有限状态自动机
4. BM 模式匹配算法
5. BM-KMP 算法
6. BF 算法
树 Tree 1. 二叉树 Binary Tree
2. 并查集 Union-Find
3. Huffman 树
数组实现的堆 Heap 1. 极大堆和极小堆 Max Heap and Min Heap
2. 极大极小堆
3. 双端堆 Deap
4. d 叉堆
树实现的堆 Heap 1. 左堆 Leftist Tree/Leftist Heap
2. 扁堆
3. 二项式堆
4. 斐波那契堆 Fibonacco Heap
5. 配对堆 Pairing Heap
查找 Search 1. 哈希表 Hash
2. 跳跃表 Skip List
3. 排序二叉树 Binary Sort Tree
4. AVL 树
5. B 树 / B+ 树 / B* 树
6. AA 树
7. 红黑树 Red Black Tree
8. 排序二叉堆 Binary Heap
9. Splay 树
10. 双链树 Double Chained Tree
11. Trie 树
12. R 树

数组和字符串

数组

数组是列表的实现方式之一,也是面试中经常涉及到的数据结构。

正如前面提到的,数组是列表的实现方式,它具有列表的特征,同时也具有自己的一些特征。然而,在具体的编程语言中,数组这个数据结构的实现方式具有一定差别。比如 C++ 和 Java 中,数组中的元素类型必须保持一致,而 Python 中则可以不同。Python 中的数组叫做 list,具有更多的高级功能

读取元素

读取数组中的元素,是通过访问索引的方式来读取的,索引一般从 0 开始。

在计算机中,内存可以看成一些已经排列好的格子,每个格子对应一个内存地址。一般情况下,数据会分散地存储在不同的格子中。

1.png

而对于数组,计算机会在内存中为其申请一段 连续 的空间,并且会记下索引为 0 处的内存地址。以数组 ["C", "O", "D", "E", "R"] 为例,它的各元素对应的索引及内存地址如下图所示。

2.png

假如我们想要访问索引为 2 处的元素 "D" 时,计算机会进行以下计算:

找到该数组的索引 0 的内存地址: 2008; 将内存地址加上索引值,作为目标元素的地址,即 2008 + 2 = 2010,对应的元素为 "D",这时便找到了目标元素。 我们知道,计算内存地址这个过程是很快的,而我们一旦知道了内存地址就可以立即访问到该元素,因此它的时间复杂度是常数级别,为 O(1)。

查找元素

假如我们对数组中包含哪些元素并不了解,只是想知道其中是否含有元素 "E",数组会如何查找元素 `"E" 呢?

4.gif

我们发现,最坏情况下,搜索的元素为 "R",或者数组中不包含目标元素时,我们需要查找 n 次,n 为数组的长度,因此查找元素的时间复杂度为 O(N),N。

插入元素

6.gif

7.gif

我们发现,如果需要频繁地对数组元素进行插入操作,会造成时间的浪费。事实上,另一种数据结构,即链表可以有效解决这个问题

删除元素

6.gif

有关数组的算法题

寻找数组的中心索引

给定一个整数类型的数组 nums,请编写一个能够返回数组 “中心索引” 的方法。

我们是这样定义数组 中心索引 的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。

如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。

示例 1:

输入:
nums = [1, 7, 3, 6, 5, 6]
输出:3
解释:
索引 3 (nums[3] = 6) 的左侧数之和 (1 + 7 + 3 = 11),与右侧数之和 (5 + 6 = 11) 相等。
同时, 3 也是第一个符合要求的中心索引。

示例 2:

输入:
nums = [1, 2, 3]
输出:-1
解释:
数组中不存在满足此条件的中心索引。

说明:

  • nums 的长度范围为 [0, 10000]。
  • 任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。 相关标签数组
public class Solution {
    public int PivotIndex(int[] nums) {
            int leftSum = 0;
            int rightSum = nums.Sum();
            for (int i = 0; i < nums.Length; i++)
            {
                if (leftSum == rightSum - leftSum - nums[i])
                    return i;
                leftSum += nums[i];
            }
            return -1;
    }
}

搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5
输出: 2

示例 2:

输入: [1,3,5,6], 2
输出: 1

示例 3:

输入: [1,3,5,6], 7
输出: 4

示例 4:

输入: [1,3,5,6], 0
输出: 0

相关标签数组 二分查找

public class Solution {
    public int SearchInsert(int[] nums, int target) {
            int length = nums.Length;
            if (nums[length - 1] < target)
            {
                return length;
            }
            int left = 0, right = length - 1, mid=0;
            while (left < right)
            {
                mid = left + (right - left) / 2;
                if (nums[mid] < target)
                    left=mid+1;
                if (nums[mid] >= target)
                    right=mid;
            }
            return left;
    }
}

合并区间

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入: intervals = [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间

提示:

- intervals[i][0] <= intervals[i] [1] 相关标签排序 数组

//暴力解法
public static int[][] Merge(int[][] intervals)
        {
            int m = 0;
            while (m < intervals.Length)
            {
                int n = 0;

                while (m==n|| n < intervals.Length&&!(intervals[m][intervals[m].Length - 1] >= intervals[n][0] && intervals[m][0] <= intervals[n][intervals[n].Length - 1]))
                    n++;
                if (n < intervals.Length)
                    intervals=ChangeArray(intervals, m, n);
                else
                    m++;     
            }
            return intervals;

        }

        private static int[][] MoveItem(int[][] intervals,int index)
        {
            while (index != intervals.Length-1)
                intervals[index] = intervals[++index];
            intervals=intervals.Skip(0).Take(intervals.Length-1).ToArray();
            return intervals;
        }


        private static int[][] ChangeArray(int[][] intervals,int m,int n)
        {
                int a = 0, b = 0;
                if (intervals[m][0] < intervals[n][0])
                    a = intervals[m][0];
                else
                    a = intervals[n][0];
                if (intervals[m][intervals[m].Length - 1] < intervals[n][intervals[n].Length - 1])
                    b = intervals[n][intervals[n].Length - 1];
                else
                    b = intervals[m][intervals[m].Length - 1];
                intervals[m][0] = a;
                intervals[m][intervals[m].Length - 1] = b;
                intervals = MoveItem(intervals, n);
            return intervals;
        }
//运行速度较快
public static int[][] Merge(int[][] intervals)
        {
            List<int[]> intList = new List<int[]>();
            for (int i = 0; i < intervals.Length; i++)
            {
                intList.Add(intervals[i]);
            }

            intList.Sort((a, b) =>
            {
                return a[0] - b[0];
            });

            List<int[]> retList = new List<int[]>();
            retList.Add(intList[0]);
            for (int j = 1; j < intList.Count; j++)
            {
                if (intList[j][0] <= retList[retList.Count - 1][retList[retList.Count-1].Length - 1])
                {
                    retList[retList.Count - 1][retList[retList.Count - 1].Length - 1] = Math.Max(retList[retList.Count - 1][retList[retList.Count - 1].Length - 1], intList[j][intList[j].Length - 1]);

                }
                else
                    retList.Add(intList[j]);
            }
            return retList.ToArray();
        }