赞
踩
最近不知是换到中文leetcode平台之后水土不服还是怎么样,感觉真的是到了瓶颈期了,最近几次打比赛真的是一次不如一次,做起来异常不顺手。
看了一下头部几位大佬们的做题耗时,基本都还是在10分钟左右,因此基本不存在这几次的题目特别难的说法,那么就是我这边自身发挥的问题了。
感觉真的是需要休息一阵子好好调整一下了,等到国庆放假的时候好好休息一下吧,但愿之后的状态能有回暖吧。。。
{{{(>_<)}}}
给出题目一的试题链接如下:
这一题的关键点就是统计只出现一行和一列中的1中的元素的个数。
因此,只要统计每一行中只有一个1的行,然后再对对应元素的列看一下是否该列中也恰好只出现了一个1。
给出python代码实现如下:
class Solution: def numSpecial(self, mat: List[List[int]]) -> int: ans = 0 n = len(mat) m = len(mat[0]) for i in range(n): eff = [] for j in range(m): if mat[i][j] == 1: eff.append((i, j)) if len(eff) == 1: j = eff[0][1] count = 0 for k in range(n): if mat[k][j] == 1: count += 1 if count == 1: ans += 1 return ans
提交代码之后评测得到:耗时168ms,占用内存14.1MB。姑且属于当前第一梯队。
给出题目二的试题链接如下:
这一题感觉是这次比赛中最蠢的一题,纯粹就是看题目的问题,问题描述极其绕嘴,比赛的时候看题目看了半天,还理解错了,然后就直接呵呵了。
等到最后终于把题目看明白之后,就直接暴力求解解决了。。。
本来以为是我自己的问题,然后现在去看了一下题目的评价,发现25个点赞,然后98个差评,呵呵。。。
算了,读者注意一下不开心的定义就行,是要同时满足两个条件,然后按照他说的规则直接暴力遍历一遍就行了,没啥技术含量,甚至说千万不要去想什么更精妙的解法,这题目纯粹就是靠怎么读题目而已!!!
直接给出代码实现如下:
class Solution: def unhappyFriends(self, n: int, preferences: List[List[int]], pairs: List[List[int]]) -> int: n = len(pairs) ans = 0 for i in range(n): x, y = pairs[i] xh = True yh = True for j in range(n): if i == j: continue u, v = pairs[j] if preferences[x].index(u) < preferences[x].index(y) and preferences[u].index(x) < preferences[u].index(v): xh = False break if preferences[x].index(v) < preferences[x].index(y) and preferences[v].index(x) < preferences[v].index(u): xh = False break for j in range(n): if i == j: continue u, v = pairs[j] if preferences[y].index(u) < preferences[y].index(x) and preferences[u].index(y) < preferences[u].index(v): yh = False break if preferences[y].index(v) < preferences[y].index(x) and preferences[v].index(y) < preferences[v].index(u): yh = False break if not xh: ans += 1 if not yh: ans += 1 return ans
提交代码之后得到:耗时472ms,占用内存27.1MB。
很挫的代码实现,但是懒得去看别人的实现了,反正没有什么量级上的差异,如果有兴趣的读者可以自行去看一下,这里就不多做介绍了。
给出题目三的试题链接如下:
这一题的本质就是求最小联通图。
普遍的算法就是Dijkstra算法,一般的数据结构课上都有,不过我有点忘了,就用了他的等价算法,Dijkstra算法是每次取连通区域外的最小边添加到图中,直到整张图都连通起来。
这边的算法名字我给忘了,不过是每次取最短边使得原本不连通的两个区域能够连通起来,直到整张图都连通起来。
给出代码实现如下:
class Solution: def minCostConnectPoints(self, points: List[List[int]]) -> int: n = len(points) distances = [[abs(x[0] - y[0]) + abs(x[1] - y[1]) for y in points] for x in points] distances = sorted((distances[x][y], x, y) for x in range(n-1) for y in range(x+1, n)) ans = 0 have_connected = [set([i]) for i in range(n)] for d, x, y in distances: if any(x in s and y in s for s in have_connected): continue s1 = -1 s2 = -1 for j, s in enumerate(have_connected): if x in s: s1 = j if y in s: s2 = j if s1 > s2: s1, s2 = s2, s1 have_connected.append(have_connected[s1] | have_connected[s2]) have_connected.pop(s2) have_connected.pop(s1) ans += d if len(have_connected) == 1: break return ans
提交代码评测得到:耗时2192ms,占用内存105.6MB。
当前最优算法耗时仅为1060ms,看了一下,使用的是Dijkstra算法。如果有感兴趣的读者可以自行实现一下,这里我就先放弃了。。。
给出题目四的试题链接如下:
这一题比赛的时候是完全没能做出来,因为一开始的思路就是错的,后来也是比赛结束之后看了一下头部几位大神们的做法,然后终于有了一些思路,后来算是终于实现出来了。
这一题的关键在于每一次的操作都是对于子序列的排序操作,因此,显然必有:原始序列中一个元素后方比他小的元素只会减少不可能会增加。
因此,要判断s序列能否通过一系列操作转换为t序列,我们只需要考察:
我们将其整理为代码实现即有:
class Solution: def isTransformable(self, s: str, t: str) -> bool: n = len(t) scounter = [{c: 0 for c in "0123456789"} for _ in range(n+1)] tcounter = [{c: 0 for c in "0123456789"} for _ in range(n+1)] for i in range(n-1, -1, -1): for c in "0123456789": scounter[i][c] = scounter[i+1][c] tcounter[i][c] = tcounter[i+1][c] scounter[i][s[i]] += 1 tcounter[i][t[i]] += 1 if not all(scounter[0][c] == tcounter[0][c] for c in "0123456789"): return False scounter_v2 = {c: [] for c in "0123456789"} for i in range(n): scounter_v2[s[i]].append(i+1) tcounter_v2 = {c: [] for c in "0123456789"} for i in range(n): tcounter_v2[t[i]].append(i+1) for c in "123456789": for idx1, idx2 in zip(scounter_v2[c], tcounter_v2[c]): if not all(scounter[idx1][str(k)] >= tcounter[idx2][str(k)] for k in range(int(c))): return False return True
上述代码提交可以通过,评测得到:耗时3332ms,占用内存104.2MB。
而当前最优代码实现耗时仅为332ms,比我们的算法高了一整个量级,因此,后续还有很大的优化空间。
需要好好看一下对方的代码实现。
感兴趣的读者可以自己先看一下,这里我就先放着了,过两天有空了再来研究一下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。