LeetCode周赛195总结
第一次做LeetCode周赛,总结一下。
听说这次好像服务器出了问题,我做的时候前40分钟巨卡无比,基本交不上。当然我本来也菜,一路踩了很多坑,最后只解决了两道半。
题目1:
给你一个字符串
path,其中path[i]的值可以是'N'、'S'、'E'或者'W',分别表示向北、向南、向东、向西移动一个单位。机器人从二维平面上的原点
(0, 0)处开始出发,按path所指示的路径行走。如果路径在任何位置上出现相交的情况,也就是走到之前已经走过的位置,请返回
True;否则,返回False。
第一题是一个hash问题,问题本身很简单(Easy),但是具体做的时候犹豫了一下,主要是考虑如何构造hash,因为我用的是C++,大概想了三个方式:
- STL的unordered_set
- STL的set
- 自己构造数组实现
首先使用了unordered_set去做,因为是一个二维坐标,所以用到了pair,但是unordered_set对于这种特殊的类型需要自定义hash函数,忽然忘记了怎么实现(其实从来也没完全记住过),所以只得换方法。
在这里记录一下unordered_map<pair<int, int>>型自定义hash函数的方法(以二维坐标为例):
1 struct pair_hash { 2 inline size_t operator()(const pair<int,int> & p) const { 3 return p.first * MAP_HEIGHT + p.second; 4 } 5 }; 6 unordered_set<pair<int, int>, pair_hash> pHash;
主要是以下几点需要注意:
- 定义在结构体中
- 以自定义运算符的形式出现
- 参数类型,返回类型
实际上,既然已经知道了hash函数的计算方式,完全没有必要再去额外定义hash函数,可以直接使用unordered_set<int>作为hash表,加入的元素是hash函数的运算结果,LeetCode的官方题解就是这样处理的。
之后使用了自己构造数组的方法,之所以没有使用第2个方法是因为考虑STL中set的红黑树实现复杂度是对数级别,但是后来发现使用set是最简单的方法...
在自己构造数组中,发现一直有未知错误,原来是又掉坑了,由于数组比较大,分配局部变量的时候数据位于栈空间,栈空间不足会导致运行时出现未知错误,所以如果真的使用这种方法需要注意分配在全局变量里面。
最后,终于使用set通过了...但是这样做应该不符合对时间复杂度有严格要求的题目吧?
题目2:
给你一个整数数组
arr和一个整数k,其中数组长度是偶数,值为n。现在需要把数组恰好分成
n / 2对,以使每对数字的和都能够被k整除。如果存在这样的分法,请返回 True ;否则,返回 False 。
首先可以看出:如果数据本身是大于k的,显然减去k对于结果没有影响,就是所有的数字在处理前应该进行取余操作简化。
然后要处理的问题是数组元素配对,满足和为k的构成一对,因此需要一个长度为k的数组进行记录。
需要注意的是负数的处理,为了方便余数统计,需要把负数处理为0-k-1之间的数如下:
xk = (x % k + k) % k
这个题目做的相对顺利一些...
题目3.
给你一个整数数组
nums和一个整数target。请你统计并返回
nums中能满足其最小元素与最大元素的 和 小于或等于target的 非空 子序列的数目。由于答案可能很大,请将结果对 10^9 + 7 取余后返回。
题目中有几个地方需要注意:
- 子序列、子串、子数组的区别
- 如何处理int溢出的数据
首先,对于子序列、子串、子数组的定义,这三个名词常出现在dp问题中,子序列是一个数组中不连续元素(连续也可)组成,子串是一个数组中连续元素组成,子数组这个说法不太严谨,一般题目中应当说明是连续子数组,否则只能根据题目用例具体判断。
在本题目中,数据的溢出出现在两个方面,一个是输出结果的存储,一个是中间过程pow计算,因此可以使用快速幂递归的方式求解(如果使用,需要取余)。实际操作中,可以开一个数组把各次幂结果保存下来,需要的时候直接取值。具体到本题,由于排序时间复杂度已经O(nlogn),pow的计算可以不使用快速幂,不会影响整体时间复杂度。但是如果题目要求不使用额外空间,则还需要利用快速幂计算。但无论那种方法,对于总体时间复杂度没有影响。
在具体做法上,首先,可以看出,子序列是数组中数据的组合,因此与是否排序无关,所以可以使用排序操作简化后续的判断流程。
一旦数组完成排序后,可以发现,一个任意子序列都对应一个数组窗口中的一种组合,因此我们只需要遍历数组,考虑满足要求的所有窗口,把窗口中的子序列个数累加起来即可。这个个数就是2^(right-left)个,表示以left开头后面的所有组合情况。
总结:
个人感觉LeetCode的选题还是挺好的,简单题直接模拟就可以得到答案,只要熟悉简单的数据结构和STL就可以;中等题一般需要两个知识点左右,一般暴力模拟是不可行的,因此一旦发现是指数复杂度的就应当考虑优化,看一下是否有dp的重叠子问题和hash解决,细节想清楚的话写起来程序不会很长。

浙公网安备 33010602011771号