leetcode热题100_medium(2)

leetcode热题100在之前的分类总结中已经完成了一部分,现在完成剩下的一部分问题

  • 394 字符串解码
  • 399 除法求值
  • 406 根据身高重建队列
  • 560 和为K的子数组
  • 621 任务调度器
  • 647 回文子串

394 字符串解码

https://leetcode-cn.com/problems/decode-string/

class Solution:
    def decodeString(self, s: str) -> str:
        '''
        栈操作,栈中存入左括号前的数字与两个左括号中间的字符串,遇到右括号出栈
        '''
        stack = []
        res = ''
        num = 0
        for i in range(len(s)):
            # 数字转换格式
            if '0'<=s[i]<='9':
                num = num  * 10 + int(s[i])
                # print(num)
            # 遇到左括号,栈中存入,此括号前的字符串与数字
            elif s[i] == '[':
                stack.append((res, num))
                res, num = '', 0
            # 遇到右括号出栈
            elif s[i] == ']':
                # last_res是一个左括号与上一个左括号中间的字符串
                last_res, num_ = stack.pop()
                # print(last_res, res, num_)
                res = last_res + num_ * res
            # res表示左括号与右括号中间的字符串
            else:
                res += s[i]
        return res

399 除法求值

https://leetcode-cn.com/problems/evaluate-division/

class Solution:
    def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
        '''
        构建一个带权图,如果x/y = v,那么x到y的权值为v,y到x的权值为1/v
        最终对于求解的每一个方程式,只需要找出特定的路径,然后将权值相乘
        '''
        # 采用dict的方式构建图
        graph = {}
        for (x, y), v in zip(equations, values):
            if x in graph:
                graph[x][y] = v
            else:
                graph[x] = {y:v}
            if y in graph:
                graph[y][x] = 1/v
            else:
                graph[y] = {x: 1/v}
        

        #dfs进行路径的查找
        def helper(s, t):
            if s not in graph: return -1
            if s == t: return 1

            for node in graph[s].keys():
                if node == t: return graph[s][node]
                else:
                    if node not in visited:
                        visited.add(node)
                        v = helper(node, t)
                        if v == -1: continue
                        else: return graph[s][node]*v
            return -1
        
        res = []
        for x, y in queries:
            visited = set()
            v = helper(x, y)
            res.append(v)
        return res
class WeightUnionFindSet:
    def __init__(self):
        self.parent = {}  # 存放父亲节点
        self.parent_div_cur = {} # 存放父亲节点除以自己的商

    def union(self, x, y, x_div_y):
        # 增加新节点
        if x not in self.parent:
            self.parent[x] = x
            self.parent_div_cur[x] = 1.0
        if y not in self.parent:
            self.parent[y] = y
            self.parent_div_cur[y] = 1.0
        
        # 寻找祖宗节点
        root_x, root_x_div_x = self.find_root(x)
        root_y, root_y_div_y = self.find_root(y)

        # 祖宗不同则进行合并
        if (root_x != root_y):
            self.parent[root_y] = root_x
            self.parent_div_cur[root_y] = root_x_div_x / root_y_div_y * x_div_y 
            # root_x / root_y = root_x / x / (root_y / y) * (x / y)
    
    def find_root(self, x):
        if self.parent[x] == x:
            return x, self.parent_div_cur[x]
        else:
            # 找到祖宗以及祖宗除以当前父节点的商
            root, root_div_parent = self.find_root(self.parent[x])
            # 路径压缩,并得到祖宗除以当前节点的商
            self.parent[x] = root
            self.parent_div_cur[x] = root_div_parent * self.parent_div_cur[x]
            return self.parent[x], self.parent_div_cur[x]

    def x_div_y(self, x, y):
        # x / y = root_y / y / (root_x / x)
        if x not in self.parent or y not in self.parent:
            return -1
        else:
            root_x, root_x_div_x = self.find_root(x)
            root_y, root_y_div_y = self.find_root(y)
            if root_x != root_y:
                return -1
            else:
                return root_y_div_y / root_x_div_x
        

class Solution:
    def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
        
        weight_union_find_set = WeightUnionFindSet()

        # 加入并查集
        for (x, y), x_div_y in zip(equations, values):
            weight_union_find_set.union(x, y, x_div_y)
        
        # 查询并查集
        ans = []
        for x, y in queries:
            ans.append(weight_union_find_set.x_div_y(x, y))

        return ans

406 根据身高重建队列

https://leetcode-cn.com/problems/queue-reconstruction-by-height/

class Solution:
    def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:

        print('init people', people)
        # 将height降序排序,将num进行升序排序
        people.sort(key = lambda x:(-x[0], x[1]))
        print('sorted people', people)

        output = []
        for p in people:
            output.insert(p[1], p)
        return output

560 和为K的子数组

https://leetcode-cn.com/problems/subarray-sum-equals-k/

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        '''
        暴力:计算所有子数组的和,判断是否为k(超时),时间复杂度为n^3
        '''
        if not nums: return 0
        L = len(nums)
        res = 0
        for i in range(L):
            for j in range(i+1, L+1):
                ij_sum = sum(nums[i:j])
                if ij_sum == k:
                    res += 1
        return res

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        '''
        动规,dp[j]表示nums[i]到nums[j]的和
        dp[j] = dp[j-1] + nums[j]
        时间复杂度为n^2,依然超时
        '''
        if not nums: return 0
        L = len(nums)
        res = 0
        dp = [0] * L
        for i in range(L):
            for j in range(i, L):
                if i == j: 
                    dp[j] = nums[j]
                    if dp[j] == k:
                        res += 1
                    continue
                dp[j] = dp[j-1] + nums[j]
                if dp[j] == k:
                    res += 1
        return res
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        '''
        利用hashmap将时间复杂度降低到N
        '''
        if not nums: return 0
        L = len(nums)
        res = 0
        dp = {}
        sums = 0
        count = 0
        for i in range(L):
            sums += nums[i]
            if sums == k:
                count += 1
            if sums -k in dp:
                count += dp[sums-k]
            dp[sums] = dp.get(sums, 0) + 1
        return count

621 任务调度器

https://leetcode-cn.com/problems/task-scheduler/

class Solution:
    def leastInterval(self, tasks: List[str], n: int) -> int:

        task_num = [0] * 26
        for c in tasks:
            task_num[ord(c)-ord('A')] += 1
        task_num.sort()
        times = 0
        while task_num[25] > 0:
            i = 0
            while i <= n:
                if task_num[25] <= 0:
                    break
                if i<26 and task_num[25-i] > 0:
                    task_num[25-i] -= 1
                times += 1
                i += 1
            task_num.sort()
        return times

647 回文子串

https://leetcode-cn.com/problems/palindromic-substrings/

class Solution:
    def countSubstrings(self, s: str) -> int:
        '''
        暴力找到所有的字串,然后判断是否回文
        '''
        if not s: return
        res = 0
        for i in range(len(s)):
            for j in range(i+1, len(s)+1):
                if s[i:j] == s[i:j][::-1]:
                    res += 1
        return res
class Solution:
    def countSubstrings(self, s: str) -> int:
        '''
        动态规划,dp[i][j]表示从i到j是否是回文串
        dp[i][j] = dp[i+1][j-1] and s[i] == s[j]
        边界条件: dp[i][i] = True
                dp[i][i+1] = s[i]==s[i+1]
        由于dp[i][j]依赖于dp[i+1][j-1],因此对于第一维数据要从下往上开始填入
        '''
        if not s: return
        res = 0
        # 上三角矩阵
        dp = [[False] * len(s) for _ in range(len(s))]
        
        # 边界条件
        for i in range(len(s)):
            dp[i][i] = True
            res += 1
            if i < len(s)-1:
                dp[i][i+1] = (s[i] == s[i+1])
                if dp[i][i+1]: res += 1

        for i in range(len(s)-2, -1, -1):
            for j in range(i+2, len(s)):
                dp[i][j] = dp[i+1][j-1] and (s[i]== s[j])
                if dp[i][j]: res+= 1

        return res

github地址

更多文章请点击查看

你可能感兴趣的:(leetcode刷题,算法,数据结构,leetcode)