Leetcode题解 - 部分中等难度算法题解(56、957、825、781、1324、816)

957. N 天后的牢房


思路:
模拟变换,当N天结合后返回 => 当N非常大的时候,超时 => 一般N很大的时候,这种题目必然存在循环,所以记录找过的状态,一旦出现已经访问过的状态可立即跳出循环。

class Solution:
    def prisonAfterNDays(self, cells, N: int):
        vis = []
        while 1:
            if not N:
                return cells
            if cells in vis:
                ind = vis.index(cells)
                break
            tcell = cells.copy()
            for i in range(len(cells)):
                if i == 0 or i == len(cells)-1:
                    tcell[i] = 0
                    continue
                if cells[i-1] == cells[i+1]:
                    tcell[i] = 1
                else:
                    tcell[i] = 0
            vis.append(cells)
            cells = tcell
            N -= 1
        vis = vis[ind:]
        return vis[N % len(vis)]

825. 适龄的朋友


思路:
最直观的就是两层循环暴力,意料之中的超时了。那么就改以人为单位交友,变为以组(年龄相同的为一组)为单位交友。

还需要注意的一点就是15岁以下的没朋友,不符合第一个条件!

from collections import Counter
class Solution:
    def numFriendRequests(self, ages) -> int:
        ages, res = sorted(Counter(ages).items(), key=lambda x: x[0]), 0
        for i in range(len(ages)):
            if ages[i][0] < 15:
                continue
            res += (ages[i][1] - 1) * ages[i][1]
            for j in range(i):
                if ages[j][0] <= (ages[i][0] * 0.5 + 7):
                    continue
                else:
                    res += ages[i][1] * ages[j][1]
        return res

781. 森林中的兔子



思路:
颜色相同的兔子如果说自己有i个伙伴,那么所有伙伴都出现,该颜色对应的数字最多出现 i+1次 => 通过频率来判断,那些是同样颜色的。

"""
判断某数字出现的频次,数字0特殊处理一下
数字i出现的频次小于等于i+1时,说明大家都是一个色。
大于i+1的时候,就说明还有别的颜色,看是i+1的几倍就 i+1 * ?
"""
import math
from collections import Counter
class Solution:
    def numRabbits(self, answers) -> int:
        ans, res = Counter(answers), 0
        for num, times in ans.items():
            if not num:
                res += times
            else:
                if times <= num + 1:
                    res += num + 1
                else:
                    t = math.ceil(times / (num + 1))
                    res += t * (num + 1)
        return res

1324. 竖直打印单词


思路:
补上空格,矩阵转置输出,末尾的空格需要去掉。

class Solution:
    def printVertically(self, s: str):
        s = s.split(" ")
        l = len(sorted(s, key=lambda x:-len(x))[0])
        for i in range(len(s)):
            s[i] = s[i] + (l - len(s[i])) * " "
        res = []
        for i in zip(*s):
            i = ("".join(list(i))).rstrip()
            res.append(i)
        return res

816. 模糊坐标


思路:
分割数组找到整数、小数部分。比较麻烦在于加上小数点后时候合理:

  1. 不是‘0’也不是‘0.‘但以0开头的不合理
  2. 以‘0’结尾的不合理
"""
先分割字符串,得到整数部分和小数部分,再分别为两部分加上小数点,同时判断加上小数点后是否为合理数字
"""
class Solution:
    def ambiguousCoordinates(self, S: str):
        def produce(string):
            res = []
            # 本身就是一个完整的数字
            if len(str(int(string))) == len(string):
                res = [string]
            # 如果全是零直接返回
            if set(string) == {'0'}:
                return res
            # 在不同的位置添加小数点
            for i in range(1,len(string)):
                t = string[:i]+"."+string[i:]
                # 不是'0'也不是'0.'开头的,以'0'开头的都要删掉
                if len(string[:i]) >= 2 and string[:i].startswith("0"):
                    continue
                # '0'结尾的也删掉
                if string[i:].endswith('0'):
                    continue
                res.append(t)
            return res
        S, res, r = S[1:-1], [], []
        # 分割字符串获取整数、小数部分
        for i in range(1, len(S)):
            res.append((S[:i], S[i:]))
        for x, y in res:
            px = produce(x)
            py = produce(y)
            for i in px:
                for j in py:
                    r.append("("+i+", "+j+")")
        return r

56. 合并区间


思路:
按照合并的要求来就vans了。先排序,保证遍历的时候后面的要么是头比前面大,要么是尾巴更长。记录当前拼接的头尾,如果遇到了头比当前拼接的尾巴还大,这两个区间不可能合并的,重新开始一次拼接,否则更新尾巴。

class Solution:
    def merge(self, intervals):
        res = []
        # 先排序
        intervals = sorted(intervals)
        # 记录拼接的首尾大小
        s, e = intervals[0][0], intervals[0][1]
        for x, y in intervals[1:]:
            # 你的头大于我的尾部,不可能拼接的。重新开始一次拼接
            if x > e:
                res.append([s, e])
                s, e = x, y
                continue
            # 可以拼接到一起,更新尾巴
            if y > e:
                e = y
        if [s, e] not in res:
            res.append([s, e])
        return res

原文地址:https://www.cnblogs.com/NFii/p/12333744.html

时间: 2024-10-30 20:28:23

Leetcode题解 - 部分中等难度算法题解(56、957、825、781、1324、816)的相关文章

每日温度(LeetCode Medium难度算法题)题解

LeetCode 题号739中等难度 每日温度 题目描述: 根据每日 气温 列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高超过该日的天数.如果之后都不会升高,请在该位置用 0 来代替. 例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]. 提示:气温 列表长度的范围是 [1, 30000].每个气温的值的均为华氏度,都是在 [30, 100] 

Leetcode medium难度顺序题解

被迫重操旧业(?) 再不刷题面试就真要翻车了.... 好在medium题难度还比较水,幸亏它不考什么神DP或数据结构或blabla不然我还面个锤子(x) 但是现场写代码还不准出错ATP顶8住啊所以还是练练手感叭.... 就,按顺序随便做几个.点中等难度然后按题号排序这样. 2. 两数相加 高精度但是用单向链表. 一开始ATP写的很麻烦,基本思路是先把两个数字重叠的部分相加,然后再单独处理较长的数字多出来的那部分,然后再处理进位这样.一共三个while循环. 但是后来发现好像直接改一下判断条件,如

POJ 3461 Oulipo KMP算法题解

本题就是给出很多对字符串,然后问一个字符串在另外一个字符串出现的次数. 就是所谓的Strstr函数啦. Leetcode有这道几乎一模一样的题目. 使用KMP算法加速,算法高手必会的算法了. 另外看见讨论说什么使用KMP还超时,最大可能是没有真正理解next table的含义,写了错误的代码,故此虽然自己运行结果正确,但是却没有真正发挥next table的作用,使得算法退化为暴力法了,所以运行正确,但超时. KMP参考: http://blog.csdn.net/kenden23/articl

POJ 2553 The Bottom of a Graph TarJan算法题解

本题分两步: 1 使用Tarjan算法求所有最大子强连通图,并且标志出来 2 然后遍历这些节点看是否有出射的边,没有的顶点所在的子强连通图的所有点,都是解集. Tarjan算法就是模板算法了. 这里使用一个数组和一个标识号,就可以记录这个顶点是属于哪个子强连通图的了. 然后使用DFS递归搜索所有点及其边,如果有边的另一个顶点不属于本子强连通图,那么就说明有出射的边. 有难度的题目: #include <stdio.h> #include <stdlib.h> #include &l

POJ 3259 Wormholes SPFA算法题解

本题其实也可以使用SPFA算法来求解的,不过就一个关键点,就是当某个顶点入列的次数超过所有顶点的总数的时候,就可以判断是有负环出现了. SPFA原来也是可以处理负环的. 不过SPFA这种处理负环的方法自然比一般的Bellman Ford算法要慢点了. #include <stdio.h> #include <string.h> #include <limits.h> const int MAX_N = 501; const int MAX_M = 2501; const

LeetCode: Longest Substring Without Repeating Characters 题解

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest subst

POJ 2560 Freckles Prime算法题解

本题是求最小生成树. 给出的是坐标节点,然后需要根据这些坐标计算出各个点之间的距离. 除此就是标准的Prime算法了,能使用Prime的基本上都可以使用Kruskal. 这些经典的算法一定要多写,熟练掌握,否则很难灵活运用的. 而且经典的算法之所以为经典,原因之一是没那么容易自己凭空想象出来的,所以要熟练. #include <stdio.h> #include <string.h> #include <queue> #include <float.h> #

LeetCode: Maximum Depth of Binary Tree 题解

Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 题解: 题意比较清楚, 找到从root出发最长的一条路径的长度. 采用DFS即可. 相似的一道题: Minimux Depth of Binary Tree 解法: http://

POJ 2914 Minimum Cut 最小割算法题解

最标准的最小割算法应用题目. 核心思想就是缩边:先缩小最大的边,然后缩小次大的边,依此缩小 基础算法:Prime最小生成树算法 不过本题测试的数据好像怪怪的,同样的算法时间运行会差别很大,而且一样的代码替换,居然会WA.系统出错的几率很小,难倒测试系统本题会有错误? 懒得继续测试这道题的系统了,反正算法正确,AC. #include <stdio.h> #include <string.h> #include <limits.h> const int MAX_N = 5