数据结构基础训练

178 阅读4分钟

学习内容

 数组与字符串

https://leetcode-cn.com/leetbook/detail/array-and-string

这是leedcode中一本免费的学习书籍,讲的是基础的数组与字符串,正如这本书的简介所介绍的那样,“大多数面试问题都属于这个范畴”,在这里用文章记录一下我(也就是小白)的学习过程,既学习这本书,也学习如何把这类博客写好。

学习重点

学了第一章数组简介后,对于其中学习重点是什么的问题,我觉得两小节的内容都算的上是重点,一个是介绍适用于所有编程语言的抽象理论,另一个是数组基本的增删查改(CRUD BOY(^_^))。

学习心得

第一章的3个习题中,第一个是如何寻找数组的中心索引,我的思路是先对整个数组求和,再遍历数组,对减掉当前元素后值的一半判断奇偶,并与前面元素的和进行比较,可以得到结果。(PS:因为最近学 js比较多,所以代码是用 js写的。)

对于第二个搜索插入位置的问题,我的思路是先判断首尾端点,再折半查找,判断当前元素与前后元素的关系,可以得到结果。

FRVF3OFOTO_0`%K3WGQV5{T.png

我对第三个“合并区间”的问题最感兴趣。

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。

 示例 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] 可被视为重叠区间。

作者:力扣 (LeetCode) 链接:leetcode-cn.com/leetbook/re…

限于能力不够的原因,代码无论是时间还是空间,都没能超过10%。但还是是简单的记录一下我在做这道题时的思路,留待我以后有所提升后回头看看。

下面是大致思路:

graph TD
Push --> Sort --> Return

在一开始声明start和end变量,作为返回区间的两个端点值。

Push:把题目中的“假区间”稍微转化的更“细致”一点。(这也是时间开销最大的地方)

简单来说,“假区间”就是类似题目中[1,4]这种只给出了区间的两个端点,中间的数值(比如1.1,1.2,2,3等等)不存在的数组。

“细致”是将原区间转化为更偏向数学意义上的区间,在这里以0.5(由于重叠的问题,不能是1)为递增值,将[1,4]转化成了[1,1.5,2,2.5, ... ,3.5,4]

最后把里面全部的值(不是单单两个区间端点)全部压入一个新的数组。

Sort: 将上面的数组排序。

Return: 在这一步将遍历排序后的数组,如果当前元素与下一个元素的值相差大于0.5,就重置两个端点,并将重置前的区间压入需要返回的数组中,遍历完成,结果也就全部得到了。

最后是代码,有一些限于篇幅没有写出来的小细节在里面,做一个完整的记录。

代码在这(已转为c#)

 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function(intervals) {
    let nums = []
    let result = []
    let start
    let end
    intervals.forEach((val) => {
        for(var i = val[0]; i <= val[1]; i = i + 0.5){
            nums.push(i);
        }
    })
    nums = nums.sort((a,b) => a - b)
    start = nums[0]
    nums.forEach((num,index) => {
        if(nums[index + 1] - num > 0.5) {
            end = nums[index]
            result.push([start,end])
            start = nums[index + 1]
        }
    })
    result.push([start,nums[nums.length - 1]])
    return result
};

相比于另外两个习题,这个题目我没能想出一个可以用一次遍历解决问题的方法,这个代码时间复杂度大致为O (n*n) ,当然最后的排名也说明了这个问题,哈哈。

边写边看,我感觉还可以将排序后的数组去重优化一下,不过这样依然没有质的改变,感觉提升不大,甚至去重的开销相比减少的遍历开销更大也有可能。

总结:

做习题还是很有用的,一方面锻炼了思维,另一方面也熟悉了语言(比如Js的sort函数特点)。如果有幸被刷到,欢迎指点。