python刷题+leetcode(第三部分)

200.最大正方形

思路:与岛屿,水塘不同的是这个相对要规则得多,而不是求连通域,所以动态规划构造出状态转移方程即可

动态规划 if 0, dp[i][j] =0

if 1, dp[i][j] = min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])+1

class Solution:def maximalSquare(self, matrix):print('==np.array(matrix):\n', np.array(matrix))h = len(matrix)w = len(matrix[0])max_side = 0dp = [[0 for j in range(w)] for i in range(h)]print('==dp:', np.array(dp))for i in range(h):for j in range(w):if matrix[i][j] == '1' and i>0 and j>0:dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1max_side = max(max_side, dp[i][j])elif i==0:dp[i][j] = int(matrix[i][j])max_side = max(max_side, dp[i][j])elif j==0:dp[i][j] = int(matrix[i][j])max_side = max(max_side, dp[i][j])else:passprint('==dp:', np.array(dp))# print(max_side)return max_side**2matrix = [["1", "0", "1", "0", "0"], ["1", "0", "1", "1", "1"], ["1", "1", "1", "1", "1"], ["1", "0", "0", "1", "0"]]sol = Solution()
sol.maximalSquare(matrix)

201.统计全为 1 的正方形子矩阵

思路:动态规划 if 0, dp[i][j] =0

if 1, dp[i][j] = min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])+1

为1的时候 res自加1,再加上dp[i][j]增加的部分,也可以看成是dp的和

class Solution:def countSquares(self, matrix):print('==np.array(matrix)\n', np.array(matrix))h = len(matrix)w = len(matrix[0])dp = [[0 for i in range(w)] for j in range(h)]print('==np.array(dp):', np.array(dp))res = 0for i in range(h):for j in range(w):if matrix[i][j] == 1 and i > 0 and j > 0:res += 1dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1res += dp[i][j] - 1  # 减去1代表增加的矩形个数elif i==0:dp[i][j] = matrix[i][j]if matrix[i][j] == 1:res+=1elif j==0:dp[i][j] = matrix[i][j]if matrix[i][j] == 1:res+=1else:passprint('==np.array(dp):', np.array(dp))print('==after res:', res)return resmatrix = [[0, 1, 1, 1],[1, 1, 1, 1],[0, 1, 1, 1]
]
sol = Solution()
sol.countSquares(matrix)

202.平方数之和

思路:双指针 左右收缩即可

class Solution:def judgeSquareSum(self, c: int) -> bool:from math import sqrtright = int(sqrt(c))left = 0while(left <= right):sum_ = left**2 + right**2if (sum_ == c):return Trueelif sum_ > c:right -= 1else:left += 1return False

c++实现:
 

class Solution {
public:bool judgeSquareSum(int c) {long left = 0, right = sqrt(c);while(left <= right){long sum_ = left*left + right*right;if(sum_ == c){return true;}else if(sum_ > c){right--;}else{left++;}}return false;}
};

203.分发饼干

思路:排序加贪心 先给胃口小的饼干

#思路:排序加贪心 先让胃口小的孩子满足
class Solution:def findContentChildren(self, g, s):print('==g:', g)print('==s:', s)g = sorted(g)#孩子s = sorted(s)#饼干res = 0for j in range(len(s)):#遍历饼干 先给胃口小的分配if res<len(g):if g[res]<=s[j]:res+=1print('==res:', res)return resg = [1,2]
s = [1,2,3]
# g = [1, 2, 3]
# s = [1, 1]
sol = Solution()
sol.findContentChildren(g, s)

204.三角形最小路径和

 思路:动态规划

class Solution:def minimumTotal(self, triangle: List[List[int]]) -> int:for i in range(1, len(triangle)):for j in range(len(triangle[i])):if j == 0:triangle[i][j] = triangle[i-1][j] + triangle[i][j]elif j == i:triangle[i][j] = triangle[i-1][j-1] + triangle[i][j]else:triangle[i][j] = min(triangle[i-1][j-1], triangle[i-1][j]) + triangle[i][j]return min(triangle[-1])

c++:

class Solution {
public:int minimumTotal(vector<vector<int>>& triangle) {int h = triangle.size();for(int i = 1; i < triangle.size(); i++){for(int j = 0; j < triangle[i].size(); j++){if(j == 0){triangle[i][j] = triangle[i-1][j] + triangle[i][j];}else if(j == i){triangle[i][j] = triangle[i-1][j-1] + triangle[i][j];}else{triangle[i][j] = min(triangle[i-1][j-1], triangle[i-1][j]) + triangle[i][j];}}}return *min_element(triangle[h - 1].begin(), triangle[h - 1].end());}
};

205.同构字符串

思路:hash  构造映射关系

class Solution:def isIsomorphic(self, s: str, t: str) -> bool:if len(s) != len(t):return Falsedic = {}for i in range(len(s)):if s[i] not in dic:#未出现过if t[i] in dic.values():#value已经出现过之前构造的dict中了return Falsedic[s[i]] = t[i]else:#出现过if dic[s[i]]!=t[i]:return Falsereturn True# s = "egg"
# t = "add"
s="ab"
t="aa"sol = Solution()
sol.isIsomorphic(s, t)

206.单词接龙 II

思路:构建图 然后bfs

class Solution:def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:cost = {}for word in wordList:cost[word] = float("inf")cost[beginWord] = 0# print('==cost:', cost)# neighbors = collections.defaultdict(list)neighbors = {}ans = []#构建图for word in wordList:for i in range(len(word)):key = word[:i] + "*" + word[i + 1:]if key not in neighbors:neighbors[key] = []neighbors[key].append(word)else:neighbors[key].append(word)# print('==neighbors:', neighbors)q = collections.deque([[beginWord]])# q = [[beginWord]]# print('====q:', q)#bfswhile q:# path = q.popleft()path = q.pop()# print('===path:', path)cur = path[-1]if cur == endWord:ans.append(path.copy())else:for i in range(len(cur)):new_key = cur[:i] + "*" + cur[i + 1:]if new_key not in neighbors:continuefor neighbor in neighbors[new_key]:# print('==cost[cur] + 1, cost[neighbor]:', cost[cur] + 1, cost[neighbor])if cost[cur] + 1 <= cost[neighbor]:q.append(path + [neighbor])cost[neighbor] = cost[cur] + 1# print('==ans:', ans)return ans

208.最后一块石头的重量

思路1:while循环 排序从大到小 一直取前两块石头进行比较


class Solution:def lastStoneWeight(self, stones):while len(stones)>=2:stones = sorted(stones)[::-1]if stones[0]==stones[1]:stones=stones[2:]else:stones = [stones[0]-stones[1]]+stones[2:]print('===stones:', stones)return stones[-1] if len(stones) else 0stones = [2, 7, 4, 1, 8, 1]
# stones = [2, 2]
sol = Solution()
res= sol.lastStoneWeight(stones)
print('==res:', res)

更简洁写法:

class Solution:def lastStoneWeight(self, stones: List[int]) -> int:while len(stones) >= 2:stones = sorted(stones)stones.append(stones.pop() - stones.pop())return stones[0]

思路2:堆队列,也称为优先队列

import heapq
class Solution:def lastStoneWeight(self, stones):h = [-stone for stone in stones]heapq.heapify(h)print('==h:', h)while len(h) > 1:a, b = heapq.heappop(h), heapq.heappop(h)if a != b:heapq.heappush(h, a - b)print('==h:', h)return -h[0] if h else 0stones = [2, 7, 4, 1, 8, 1]
# stones = [2, 2]
sol = Solution()
res= sol.lastStoneWeight(stones)
print('==res:', res)

210.无重叠区间


class Solution:def eraseOverlapIntervals(self, intervals):n = len(intervals)if n<=0:return 0intervals = sorted(intervals, key=lambda x: x[-1])print('==intervals:', intervals)res = [intervals[0]]for i in range(1, n):if intervals[i][0] >= res[-1][-1]:res.append(intervals[i])print(res)return n - len(res)# intervals = [[1, 2], [2, 3], [3, 4], [1, 3]]
# intervals = [[1,100],[11,22],[1,11],[2,12]]
intervals = [[0, 2], [1, 3], [2, 4], [3, 5], [4, 6]]
sol = Solution()
sol.eraseOverlapIntervals(intervals)

212.种花问题

思路:判断是否是1或0,1就一种情况,0有两种情况

100 先判断1

 01000,要判断i为0时,i+1是否为1,否则说明就是001这种情况


# 100 先判断1
# 01000,要判断i为0时,i+1是否为1,否则说明就是001这种情况
class Solution:def canPlaceFlowers(self, flowerbed, n):i = 0res = 0while i<len(flowerbed):if flowerbed[i]==1:i+=2else:if i+1<len(flowerbed) and flowerbed[i+1]==1:i+=3else:res+=1i+=2return True if res>=n else False# flowerbed = [1,0,0,0,1]
# n = 1# flowerbed = [1,0,0,0,1]
# n = 2# flowerbed = [1,0,0,0,0,0,1]
# n = 2
flowerbed = [1,0,0,0,1,0,0]
n = 2
sol = Solution()
res= sol.canPlaceFlowers(flowerbed, n)
print('==res:', res)

216.较大分组的位置

其实就是再求聚类

思路1:动态规划


class Solution:def largeGroupPositions(self, s):dp = [0] * len(s)for i in range(1, len(s)):if s[i] == s[i - 1]:dp[i] = 1dp.append(0)print('==dp:', dp)index = [j for j in range(len(dp)) if dp[j] == 0]print('index:', index)res = []for k in range(len(index) - 1):if index[k + 1] - index[k] >= 3:res.append([index[k], index[k + 1] - 1])print('=res:', res)return ress = "abbxxxxzzy"
sol = Solution()
sol.largeGroupPositions(s)

思路2:双指针


# 双指针
class Solution:def largeGroupPositions(self, s):res = []left, right = 0, 0while left < len(s):right = left + 1while right < len(s) and s[right] == s[left]:right += 1if right - left >= 3:res.append([left, right - 1])# 左指针跑到右指针位置left = rightprint('==res:', res)return ress = "abbxxxxzzy"
# s = "abcdddeeeeaabbbcd"
sol = Solution()
sol.largeGroupPositions(s)

217.省份数量

思路:

可以把 n 个城市和它们之间的相连关系看成图, #

城市是图中的节点,相连关系是图中的边,

 给定的矩阵isConnected 即为图的邻接矩阵,省份即为图中的连通分量。

利用dfs将一个数组view遍历过的城市置位1。


# dfs
# 可以把 nn 个城市和它们之间的相连关系看成图,
# 城市是图中的节点,相连关系是图中的边,
# 给定的矩阵isConnected 即为图的邻接矩阵,省份即为图中的连通分量。
class Solution:def travel(self, isConnected, i, n):self.view[i] = 1  # 表示已经遍历过for j in range(n):if isConnected[i][j] == 1 and not self.view[j]:self.travel(isConnected, j, n)def findCircleNum(self, isConnected):n = len(isConnected)self.view = [0] * nres = 0for i in range(n):if self.view[i] != 1:res += 1self.travel(isConnected, i, n)print('==res:', res)return res# isConnected = [[1, 1, 0],
#                [1, 1, 0],
#                [0, 0, 1]]
isConnected = [[1,0,0],[0,1,0],[0,0,1]]
sol = Solution()
sol.findCircleNum(isConnected)

218.旋转数组

思路1:截断拼接,注意的是一些边界条件需要返回原数组

class Solution:def rotate(self, nums: List[int], k: int) -> None:if len(nums)<=1 or k==0 or k%len(nums)==0:return numsn = len(nums)k = k%n# print(nums[-k:]+nums[:n-k])nums[:] = nums[-k:]+nums[:n-k]return nums

思路2:先左翻转,在右翻转,在整体翻转 


class Solution:def reverse(self, i, j, nums):#交换位置的while i < j:#nums[i], nums[j] = nums[j], nums[i]i += 1j -= 1def rotate(self, nums, k):"""Do not return anything, modify nums in-place instead."""n = len(nums)k %= n #有大于n的数self.reverse(0, n - k - 1, nums) #左翻self.reverse(n - k, n - 1, nums) #右翻self.reverse(0, n - 1, nums) #整体翻print(nums)return nums# nums = [1,2,3,4,5,6,7]
# k = 3
nums = [1,2,3,4,5,6]
k = 11
sol = Solution()
sol.rotate(nums, k)

219.汇总区间

思路:双指针


class Solution:def summaryRanges(self, nums):res = []left =0right = 0while right<len(nums):right = left+1while right<len(nums) and nums[right] - nums[right-1] == 1:right+=1if right -1>left:res.append(str(nums[left]) + "->" + str(nums[right-1]))else:res.append(str(nums[left]))left = rightprint(res)return res
nums = [0,1,2,4,5,7]
sol = Solution()
sol.summaryRanges(nums)

220.冗余连接

思路:并查集


#并查集:合并公共节点的,对相邻节点不是公共祖先的进行合并
class Solution:def find(self, index):  # 查询if self.parent[index] == index:  # 相等就返回return indexelse:return self.find(self.parent[index])  # 一直递归找到节点index的祖先def union(self, i, j):  # 合并self.parent[self.find(i)] = self.find(j)def findRedundantConnection(self, edges):nodesCount = len(edges)self.parent = list(range(nodesCount + 1))print('==self.parent:', self.parent)for node1, node2 in edges:print('==node1, node2:', node1, node2)if self.find(node1) != self.find(node2):#相邻的节点公共祖先不一样就进行合并print('===hahhaha===')self.union(node1, node2)print('=self.parent:', self.parent)else:return [node1, node2]return []edges = [[1, 2], [1, 3], [2, 3]]
sol = Solution()
res = sol.findRedundantConnection(edges)
print('=res:', res)

223.可被 5 整除的二进制前缀

思路:二进制移位 在和5求余

class Solution:def prefixesDivBy5(self, A: List[int]) -> List[bool]:res = [False]*len(A)value = 0for i in range(len(A)):value = (value<<1) + A[i]# print(value)if value%5==0:res[i]=Truereturn res

225.移除最多的同行或同列石头

思路1: 其实主要是算连通域的个数,当满足同行或者同列就算联通,
 输出的结果就是石头个数减去连通域个数,第一种解法超时


# 其实主要是算连通域的个数,当满足同行或者同列就算联通,
# 输出的结果就是石头个数减去连通域个数
#第一种直接dfs会超时
import numpy as np
class Solution:def dfs(self, rect, i, j, h, w):if i < 0 or i >= h or j < 0 or j >= w or rect[i][j] != 1:returnrect[i][j] = -1for i_ in range(h):self.dfs(rect, i_, j, h, w)for j_ in range(w):self.dfs(rect, i, j_, h, w)def removeStones(self, stones):n = 10rect = [[0 for _ in range(n)] for _ in range(n)]print(len(rect))for stone in stones:rect[stone[0]][stone[-1]] = 1print('before np.array(rect):', np.array(rect))h, w = n, ngraphs = 0for i in range(h):for j in range(w):if rect[i][j] == 1:graphs += 1self.dfs(rect, i, j, h, w)print('after np.array(rect):', np.array(rect))print(graphs)return len(stones) - graphsstones = [[0, 0], [0, 1], [1, 0], [1, 2], [2, 1], [2, 2]]
sol = Solution()
res = sol.removeStones(stones)
print('===res:', res)

思路2:并查集


class Solution:# 并查集查找def find(self, x):if self.parent[x] == x:return xelse:return self.find(self.parent[x])#合并def union(self,i, j):self.parent[self.find(i)] = self.find(j)def removeStones(self, stones):# 因为x,y所属区间为[0,10^4]# n = 10001n = 10self.parent = list(range(2 * n))for i, j in stones:self.union(i, j + n)print('==self.parent:', self.parent)# 获取连通区域的根节点res = []for i, j in stones:res.append(self.find(i))print('=res:', res)return len(stones) - len(set(res))stones = [[0, 0], [0, 1], [1, 0], [1, 2], [2, 1], [2, 2]]
sol = Solution()
res = sol.removeStones(stones)
print('===res:', res)

226..缀点成线

思路:判断斜率 将除换成加


class Solution:def checkStraightLine(self, coordinates):n = len(coordinates)for i in range(1, n-1):if (coordinates[i+1][1]-coordinates[i][1])*(coordinates[i][0]-coordinates[i-1][0])=(coordinates[i][1]-coordinates[i-1][1])*(coordinates[i+1][0]-coordinates[i][0]):return Falsereturn Truecoordinates = [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]
sol = Solution()
sol.checkStraightLine(coordinates)

227.账户合并

思路:并查集

#思想是搜索每一行的每一个邮箱,如果发现某一行的某个邮箱在之前行出现过,那么把该行的下标和之前行通过并查集来合并,
class Solution(object):def find(self, x):if x == self.parents[x]:return xelse:return self.find(self.parents[x])def union(self,i, j):self.parents[self.find(i)] = self.find(j)def accountsMerge(self, accounts):# 用parents维护每一行的父亲节点# 如果parents[i] == i, 表示当前节点为根节点self.parents = [i for i in range(len(accounts))]print('==self.parents:', self.parents)dict_ = {}# 如果发现某一行的某个邮箱在之前行出现过,那么把该行的index和之前行合并(union)即可for i in range(len(accounts)):for email in accounts[i][1:]:if email in dict_:self.union(dict_[email], i)else:dict_[email] = iprint('===self.parents:', self.parents)print('=== dict_:', dict_)import collectionsusers = collections.defaultdict(set)print('==users:', users)res = []# 1. users:表示每个并查集根节点的行有哪些邮箱# 2. 使用set:避免重复元素# 3. 使用defaultdict(set):不用对每个没有出现过的根节点在字典里面做初始化for i in range(len(accounts)):for account in accounts[i][1:]:users[self.find(i)].add(account)print('==users:', users)# 输出结果的时候注意结果需按照字母顺序排序(虽然题目好像没有说)for key, val in users.items():res.append([accounts[key][0]] + sorted(list(val)))return resaccounts = [["John", "johnsmith@mail.com", "john00@mail.com"],["John", "johnnybravo@mail.com"],["John", "johnsmith@mail.com", "john_newyork@mail.com"],["Mary", "mary@mail.com"]]# [["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'],
#  ["John", "johnnybravo@mail.com"],
#  ["Mary", "mary@mail.com"]]sol = Solution()
res= sol.accountsMerge(accounts)
print(res)

228.连接所有点的最小费用

思路1: 其实就是求最小生成树,首先想到的是kruskal 但是时间复杂度较高,超时


# 其实就是求最小生成树:采用kruskal 但是时间复杂度较高,超时
class Solution:def minCostConnectPoints(self, points):edge_list = []nodes = len(points)for i in range(nodes):for j in range(i):dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])edge_list.append([i, j, dis])print('==edge_list:', edge_list)edge_list = sorted(edge_list, key=lambda x: x[-1])print('==edge_list:', edge_list)group = [[i] for i in range(nodes)]print('==group:', group)res = 0for edge in edge_list:for i in range(len(group)):if edge[0] in group[i]:m = i  # 开始节点if edge[1] in group[i]:n = i  # 结束节点if m != n:# res.append(edge)res += edge[-1]group[m] = group[m] + group[n]group[n] = []print(group)print('==res:', res)return respoints = [[0, 0], [2, 2], [3, 10], [5, 2], [7, 0]]
sol = Solution()
sol.minCostConnectPoints(points)

思路2: 其实就是求最小生成树,首先想到的是prim 但是时间复杂度较高,超时


# prim算法 超出时间限制
class Solution:def minCostConnectPoints(self, points):# edge_list = []nodes = len(points)Matrix = [[0 for i in range(nodes)] for j in range(nodes)]for i in range(nodes):for j in range(nodes):dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])# edge_list.append([i, j, dis])Matrix[i][j] = dis# print('===edge_list:', edge_list)print('==Matrix:', Matrix)selected_node = [0]candidate_node = [i for i in range(1, nodes)]  # 候选节点print('==candidate_node:', candidate_node)# res = []res = 0while len(candidate_node):begin, end, minweight = 0, 0, float('inf')for i in selected_node:for j in candidate_node:if Matrix[i][j] < minweight:minweight = Matrix[i][j]begin = i  # 存储开始节点end = j  # 存储终止节点# res.append([begin, end, minweight])print('==end:', end)res += minweightselected_node.append(end)  # 找到权重最小的边 加入可选节点candidate_node.remove(end)  # 候选节点被找到 进行移除print('==res:', res)return respoints = [[0, 0], [2, 2], [3, 10], [5, 2], [7, 0]]
# points = [[-1000000, -1000000], [1000000, 1000000]]
sol = Solution()
sol.minCostConnectPoints(points)

思路3:并查集


class Solution:def find(self, x):if self.parents[x] == x:return xelse:return self.find(self.parents[x])  # 一直找到帮主def union(self, i, j):  # 替换为帮主 站队self.parents[self.find(i)] = self.find(j)def minCostConnectPoints(self, points):costs_list = []n = len(points)for i in range(n):for j in range(i + 1, n):dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])costs_list.append([dis, i, j])# print('==costs_list:', costs_list)costs_list = sorted(costs_list, key=lambda x: x[0])print('==costs_list:', costs_list)self.parents = [i for i in range(n)]print('==init self.parents:', self.parents)res = 0for i in range(len(costs_list)):dis, x, y = costs_list[i]if self.find(x) != self.find(y):self.union(x, y)print('==x,y:', x, y)print('==self.parents:', self.parents)res += disprint('==res:', res)return respoints = [[0, 0], [2, 2], [3, 10], [5, 2], [7, 0]]
sol = Solution()
sol.minCostConnectPoints(points)

229.正则表达式匹配

思路:字符串的匹配问题,自然想到用dp,做成二维矩阵方便进行状态方程的转移

f[i][j]:s的前i个字符和p的前j个字符是否相等
p的第j个字符是字母:p[j]==s[i]时 ,f[i][j]=f[i-1][j-1]
p的第j个字符是字母:p[j]!=s[i]时 ,f[i][j]=False

p的第j个字符是*:s[i]==p[j-1],f[i][j]=f[i-1][j] or f[i][j-2]
p的第j个字符是*:s[i]!=p[j-1],f[i][j]=f[i][j-2]


#f[i][j]:s的前i个字符和p的前j个字符是否相等
#p的第j个字符是字母:p[j]==s[i]时 ,f[i][j]=f[i-1][j-1]
#p的第j个字符是字母:p[j]!=s[i]时 ,f[i][j]=False#p的第j个字符是*:s[i]==p[j-1],f[i][j]=f[i-1][j] or f[i][j-2]
#p的第j个字符是*:s[i]!=p[j-1],f[i][j]=f[i][j-2]
class Solution:def match(self, i, j, s, p):if i == 0:return Falseif p[j - 1] == '.':return Truereturn s[i - 1] == p[j - 1]def isMatch(self, s, p):m, n = len(s), len(p)f = [[False] * (n + 1) for _ in range(m + 1)]f[0][0] = Truefor i in range(m + 1):for j in range(1, n + 1):if p[j - 1] == '*':# f[i][j] = f[i][j] or f[i][j - 2]if self.match(i, j - 1, s, p):f[i][j] = f[i - 1][j] or f[i][j-2]else:f[i][j] = f[i][j - 2]else:if self.match(i, j, s, p):f[i][j] = f[i - 1][j - 1]else:f[i][j] = Falseprint('==f:', f)return f[m][n]s = "aa"
p = "a"
sol = Solution()
sol.isMatch(s, p)

230.最长回文子串

思路:中心枚举,双指针,需要注意的是有上述两种情况,左右指针的索引有两种


class Solution:def help(self, left, right, s, n):while left >= 0 and right < n:if s[left] == s[right]:left -= 1right += 1else:breaktemp = s[left+1:right]self.res = max(self.res, temp, key=len)def longestPalindrome(self, s):self.res = s[0]n = len(s)for i in range(1, n):self.help(i-1, i+1, s, n)#针对"babad"self.help(i - 1, i, s, n)#针对"cbbd"print('==self.res:', self.res)return self.res# s = "babad"
s = "cbbd"
sol = Solution()
sol.longestPalindrome(s)

231.寻找两个正序数组的中位数

思路:双指针,走完剩下的在进行合并


class Solution:def findMedianSortedArrays(self, nums1, nums2):res = []i, j = 0, 0m, n = len(nums1), len(nums2)while i < m and j < n:if nums1[i] < nums2[j]:res.append(nums1[i])i += 1else:res.append(nums2[j])j += 1print('==res:', res)print('==i:', i)print('==j:', j)if i < m:res.extend(nums1[i:])if j < n:res.extend(nums2[j:])print('==res:', res)if (m+n)%2==0:#偶数return (res[(m+n)//2]+res[(m+n)//2-1])/2else:#奇数return res[(m+n)//2]# nums1 = [1, 1, 3]
# nums2 = [2]
nums1 = [1,2]
nums2 = [3,4]
sol = Solution()
res = sol.findMedianSortedArrays(nums1, nums2)
print(res)

232.连通网络的操作次数

思路:并查集 其实就是求当前的联通量个数减去一个联通量的值,对于n个节点,要给n-1条边才会满足都能连上,采用并查集去做聚类,否则就不满足了


class Solution:def find(self, x):if x==self.parent[x]:return xelse:return self.find(self.parent[x])def union(self,x,y):#将x的老大换成y的老大self.parent[self.find(x)] = self.find(y)def makeConnected(self, n, connections):if len(connections) < n - 1:return -1self.parent = [i for i in range(n)]clusters = nfor connection in connections:x, y = connectionif self.find(x)!=self.find(y):clusters-=1self.union(x, y)print('==x,y', x, y)print('==self.parent:', self.parent)print(clusters)return clusters-1n = 4
connections = [[0,1],[0,2],[1,2]]
sol = Solution()
sol.makeConnected(n, connections)

234.最长连续递增序列

思路:栈


class Solution:def findLengthOfLCIS(self, nums):stack = []res = 0for i in range(len(nums)):if stack and nums[i]<=stack[-1]:stack=[]stack.append(nums[i])res = max(len(stack), res)# print('==stack:', stack)# print(res)return res
nums = [1, 3, 5, 4, 7]
sol = Solution()
sol.findLengthOfLCIS(nums)

235.由斜杠划分区域

思路;把斜线换成3*3网格,就变成水域问题了

import numpy as npclass Solution:def dfs(self, i, j, h, w, matrix):if i < 0 or j < 0 or i >= h or j >= w or matrix[i][j] != 0:returnmatrix[i][j] = -1self.dfs(i - 1, j, h, w, matrix)self.dfs(i, j - 1, h, w, matrix)self.dfs(i + 1, j, h, w, matrix)self.dfs(i, j + 1, h, w, matrix)def regionsBySlashes(self, grid):n = len(grid)matrix = [[0 for _ in range(3 * n)] for _ in range(3 * n)]print(np.array(matrix))for i in range(n):for j in range(len(grid[i])):if grid[i][j] == '/':matrix[i * 3][j * 3 + 2] = matrix[i * 3 + 1][j * 3 + 1] = matrix[i * 3 + 2][j * 3] = 1elif grid[i][j] == '\\':matrix[i * 3 + 2][j * 3 + 2] = matrix[i * 3 + 1][j * 3 + 1] = matrix[i * 3][j * 3] = 1print(np.array(matrix))res = 0for i in range(3 * n):for j in range(3 * n):if matrix[i][j] == 0:res+=1self.dfs(i, j, 3 * n, 3 * n, matrix)print('==res:', res)return res# grid = [" /", "/ "]
grid = ["/\\", "/\\"]
sol = Solution()
sol.regionsBySlashes(grid)

要注意的是如果格子用2*2,会出现这种0不会挨着的,会出错

236.等价多米诺骨牌对的数量

思路1;

两层循环 超时

class Solution:def numEquivDominoPairs(self, dominoes):#两层循环 超时n = len(dominoes)left, right = 0, 0res=0while left<n:right=left+1while right<n:if dominoes[right]==dominoes[left][::-1] or dominoes[right]==dominoes[left]:res+=1right+=1left+=1print('==res:', res)return res

思路2:做成字典,记录相同的个数,两两之间相互组合为n*(n-1)/2


class Solution:def numEquivDominoPairs(self, dominoes):# 字典法ans = 0dict_ = {}for d1, d2 in dominoes:# 排序后加入字典index = tuple(sorted((d1, d2)))if index in dict_:dict_[index] += 1else:dict_[index] = 1print('==dict_:', dict_)# 计算答案for i in dict_:#n*n(-1)/2ans += dict_[i] * (dict_[i] - 1) // 2return ans

思路3:桶计数,两两之间相互组合为n*(n-1)/2


class Solution:def numEquivDominoPairs(self, dominoes):      #桶装法nums = [0]*100res = 0for dominoe in dominoes:x,y = dominoeif x>y:nums[x*10+y] +=1else:nums[y * 10 + x] += 1for num in nums:if num>=2:res += num*(num-1)//2print(res)return res

239.寻找数组的中心索引

class Solution:def pivotIndex(self, nums):n = len(nums)for i in range(n):left_sum = sum(nums[:i])right_sum = sum(nums[i+1:])if left_sum == right_sum:return ireturn -1nums = [1, 7, 3, 6, 5, 6]
sol = Solution()
res = sol.pivotIndex(nums)
print(res)

240.最小体力消耗路径

思路1:咋一眼看过去,以为直接用dp就行,但是真正在写的过程中,发现消耗的最小体力没有状态转移方程,所以可不可以看成先初始化给一个体力值,如果能达到右下脚,将体力值减少,而这个减少的过程采用二分法这样减少更快

代码注释的部分使用list会超时,换成集合就好了,不会超时


# 思路:二分法,先给定一个初始体力值,能够走到的话,就减少体力,否则增加体力
class Solution:def minimumEffortPath(self, heights):h, w = len(heights), len(heights[0])left_value, right_value, res = 0, 10 ** 6 - 1, 0# 二分法while left_value <= right_value:  # 终止条件 找到合适的体力值mid = left_value + (right_value - left_value) // 2# start_point = [[0, 0]]# seen = [[0, 0]]start_point = [(0, 0)]seen = {(0, 0)}while start_point:x, y = start_point.pop(0)for x_, y_ in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]:# 不超过范围 也没见过 差值也小与给定的体力值# if 0 <= x_ < h and 0 <= y_ < w and [x_, y_] not in seen and abs(#         heights[x][y] - heights[x_][y_]) <= mid:#     start_point.append([x_, y_])#     seen.append([x_, y_])if 0 <= x_ < h and 0 <= y_ < w and (x_, y_) not in seen and abs(heights[x][y] - heights[x_][y_]) <= mid:start_point.append((x_, y_))seen.add((x_, y_))print('==seen:', seen)if (h - 1, w - 1) in seen:  # 足够到底右下角,说明体力足够,那么继续减少体力res = midright_value = mid - 1else:  # 到不了右下角,说明体力不够,需要增加体力left_value = mid + 1return resheights = [[1, 2, 2],[3, 8, 2],[5, 3, 5]]
sol = Solution()
res = sol.minimumEffortPath(heights)
print('==res:', res)

思路2:并查集
将节点与节点之间的边与权重构建出来
按权重从小到大 不断合并 只要出现从起始点到终止点能够到达 说明找到了 此时的值就是最大消耗体力值


#思路:并查集
#将节点与节点之间的边与权重构建出来
#按权重从小到大 不断合并 只要出现从起始点到终止点能够到达 说明找到了 此时的值就是最大消耗体力值
class Solution:def find(self, x):if x==self.parent[x]:return xelse:return self.find(self.parent[x])def union(self, x, y):#将y的老大换成x的老大x = self.find(x)y = self.find(y)if x == y:return Falseif self.size[x]<self.size[y]:x, y = y, xself.parent[y] = xself.size[x] += self.size[y]#x的老大进行计数 看哪边人多 那边人多 就归属def connect(self,x, y):x,y = self.find(x),self.find(y)return x==ydef minimumEffortPath(self, heights):h, w = len(heights), len(heights[0])self.parent = [i for i in range(h*w)]self.size = [1 for _ in range(h*w)]edges = []#构建 节点和节点之间的边和权重for i in range(h):for j in range(w):index = i*w+jif i>0:edges.append((index-w, index, abs(heights[i][j]-heights[i-1][j])))#减去一行的宽度 回到上一行 也就是竖线的边if j>0:edges.append((index-1,index,abs(heights[i][j]-heights[i][j-1])))#减去左边一格  回到左边 也就是横线的边print('==edges:', edges)print(len(edges))edges = sorted(edges, key=lambda x: x[2])#按权重重小到大排序print('==edges:', edges)res = 0for x, y, value in edges:self.union(x, y)#把y的老大换成x的老大print('==self.parent:', self.parent)print('==self.size:', self.size)if self.connect(0, h*w-1):res = valuebreakprint('==res:', res)return resheights = [[1, 2, 2],[3, 8, 2],[5, 3, 5]]
# heights  = [[4,3,4,10,5,5,9,2],
#             [10,8,2,10,9,7,5,6],
#             [5,8,10,10,10,7,4,2],
#             [5,1,3,1,1,3,1,9],
#             [6,4,10,6,10,9,4,6]]
sol = Solution()
res = sol.minimumEffortPath(heights)
print('==res:', res)

241.不用加减乘除做加法

思路:分为进位和 当前位的异或

class Solution:def add(self, a: int, b: int) -> int:add_flag = (a&b)<<1;#进位在左移sum_ = a^b;#异或 取值 相同为0 不同为1return sum_+add_flag

242.水位上升的泳池中游泳

堆队列 也称为优先队列 就是根节点的值最小

思路:采用bfs + 堆队列  保证能到达左下角的时候 需要最小的时间


# 堆队列 也称为优先队列 就是根节点的值最小
# 思路:采用dfs + 堆队列
import heapqclass Solution:def swimInWater(self, grid):h, w = len(grid), len(grid[0])res = 0heap = [(grid[0][0], 0, 0)]visited = {(0, 0)}while heap:print('===heap:', heap)height, x, y = heapq.heappop(heap)res = max(res, height)if x == w - 1 and y == h - 1:return resfor dx, dy in ((0, 1), (0, -1), (1, 0), (-1, 0)):new_x, new_y = x + dx, y + dyif 0 <= new_x < w and 0 <= new_y < h and (new_x, new_y) not in visited:visited.add((new_x, new_y))heapq.heappush(heap, (grid[new_x][new_y], new_x, new_y))return -1grid = [[0, 2],[1, 3]]
# grid = [[0, 1, 2, 3, 4],
#         [24, 23, 22, 21, 5],
#         [12, 13, 14, 15, 16],
#         [11, 17, 18, 19, 20],
#         [10, 9, 8, 7, 6]]
sol = Solution()
sol.swimInWater(grid)

243.从相邻元素对还原数组

思路:构建字典,进行bfs遍历 依次对出现过一次的字符 添加进列表即可

#bfs
class Solution():def restoreArray(self, adjacentPairs):""":type adjacentPairs: List[List[int]]:rtype: List[int]"""import collectionsmemory = collections.defaultdict(list)for x,y in adjacentPairs:memory[x].append(y)memory[y].append(x)print('==memory:', memory)res = []visited = set()queue = []for key, value in memory.items():if len(value) == 1:queue.append((key, value[0]))while queue:print('==queue:', queue)start, end = queue.pop()res.append(start)print('==res:', res)visited.add(start)for num in memory[end]:if num in visited:continuequeue.append((end, num))return resadjacentPairs = [[2,1],[3,4],[3,2]]
# # adjacentPairs = [[4,-2],
# #                  [1,4],
# #                  [-3,1]]
# # adjacentPairs = [[100000,-100000]]
# adjacentPairs =[[4,-10],
#                 [-1,3],
#                 [4,-3],
#                 [-3,3]]
sol = Solution()
ress= sol.restoreArray(adjacentPairs)
print(ress)

246.公平的糖果棒交换

#思路1:两层for循环 超时

#思路1:两层for循环 超时
class Solution:def fairCandySwap(self, A, B):sum_A = sum(A)sum_B = sum(B)target = (sum_A+sum_B)//2for i in range(len(A)):for j in range(len(B)):if sum(A[:i])+sum(A[i+1:])+B[j] == target:return [A[i], B[j]]return []# A = [1, 2]
# B = [2, 3]
A = [1 ,2, 5]
B = [2, 4]
sol = Solution()
res = sol.fairCandySwap(A, B)
print(res)

 思路2:双指针 利用 sumA-x+y = sumB+x-y -->(sumA-sumB)/2 = x-y  转换为寻找两个元素

#思路1:#sumA-x+y = sumB+x-y -->(sumA-sumB)/2 = x-y
# 故用双指针 转换为二分查找 去查找两数之差
class Solution:def fairCandySwap(self, A, B):i = 0j = 0A = sorted(A)B = sorted(B)sum_A  = sum(A)sum_B = sum(B)target = (sum_A-sum_B)/2print('==target:', target)while i<len(A) and j<len(B):if (A[i] - B[j]) == target:return [A[i], B[j]]elif (A[i] - B[j])>target:j+=1else:i+=1return []# A = [1, 2]
# B = [2, 3]
A = [1,2,5]
B = [2,4]
sol = Solution()
res = sol.fairCandySwap(A, B)
print(res)

思路3:一层for循环 利用 sumA-x+y = sumB+x-y -->(sumA-sumB)/2 = x-y  转换为寻找两个元素

#思路2:#sumA-x+y = sumB+x-y -->(sumA-sumB)/2 = x-y
# 一层for循环走遍
class Solution:def fairCandySwap(self, A, B):sum_A = sum(A)sum_B = sum(B)target = (sum_A-sum_B)//2for num in B:if num+target in A:return [num+target, num]return []A = [1, 2]
B = [2, 3]
# A = [1 ,2, 5]
# B = [2, 4]
sol = Solution()
res = sol.fairCandySwap(A, B)
print(res)

247.替换后的最长重复字符

思路:如果k==0其实就是求最长字符串 ,k大于0,那么采用滑动窗口的方式 对左右指针求最少字符(也可能是不同字符)个数

如果最少字符个数大于k说明 左指针该右移动了,否则右指针一直在右移

# 思路:如果k==0其实就是求最长字符串 ,k大于0,那么采用滑动窗口的方式 对左右指针求最少字符个数
# 如果最少字符个数大于k说明 左指针改右移动了,否则右指针一直在右移
class Solution:def characterReplacement(self, s, k):left, right = 0, 0nums = [0] * 26# max_num = 0res = 0while right < len(s):nums[ord(s[right]) - ord('A')] += 1max_num = max(nums)#减去max_num 就是 求左右指针内最少字符(也可能是不同字符)个数while right - left + 1 - max_num > k:nums[ord(s[left]) - ord('A')] -= 1left += 1right += 1res = max(right - left, res)print('==res:', res)return res# s = "ABAB"
# k = 2
s = "AABABBA"
k = 1
sol = Solution()
res = sol.characterReplacement(s, k)
print('==res:', res)

250.子数组最大平均数 I

思路1:采用list和 ,超时

class Solution:def findMaxAverage(self, nums, k):res = float('-inf')for i in range(len(nums)-k+1):res = max(sum(nums[i:i+k]), res)print(res)return res/knums = [1, 12, -5, -6, 50, 3]
k = 4
sol = Solution()
sol.findMaxAverage(nums, k)

思路2:采用前缀和,空间换时间

class Solution:def findMaxAverage(self, nums, k):length =len(nums)pre_sum = [0]*lengthpre_sum[0] = nums[0]for i in range(1, length):pre_sum[i] = pre_sum[i-1]+nums[i]print('===pre_sum:', pre_sum)res = float('-inf')for i in range(k-1, length):if i > k-1:res = max(res, pre_sum[i] - pre_sum[i-k])else:res = pre_sum[i]print('==res:', res)return res/knums = [1, 12, -5, -6, 50, 3]
k = 4
sol = Solution()
res = sol.findMaxAverage(nums, k)
print('==res:', res)

思路3:双指针

class Solution:def findMaxAverage(self, nums, k):length = len(nums)Sum = 0res = float('-inf')left,right=0,0while right<length:Sum += nums[right]if right>=k-1:res =max(res, Sum)print('==res:', res)Sum-=nums[left]left += 1right+=1return res/knums = [1, 12, -5, -6, 50, 3]
k = 4
sol = Solution()
res = sol.findMaxAverage(nums, k)
print('==res:', res)

251.尽可能使字符串相等

思路;转换成距离列表后进行双指针滑动窗口即可

#双指针
class Solution:def equalSubstring(self, s, t, maxCost):length = len(s)dist_cost = [0] * lengthfor i in range(length):dist_cost[i] = abs(ord(s[i]) - ord(t[i]))print('==dist_cost:', dist_cost)res = 0left,right =0,0Sum = 0while right<length:Sum+=dist_cost[right]if Sum>maxCost:Sum -= dist_cost[left]left+=1right+=1res = max(res, right - left)print(res)return res
# s = "abcd"
# t = "bcdf"
# cost = 3
# s = "abcd"
# t = "acde"
# cost = 0
s = "krrgw"
t = "zjxss"
cost = 19
# s = "abcd"
# t = "cdef"
# cost = 3
sol = Solution()
sol.equalSubstring(s, t, cost)

261.可获得的最大点数

思路:转换为求连续的和最小, 那么自然用滑动窗口解决即可以

class Solution:def maxScore(self, cardPoints, k):length = len(cardPoints)leaving_k = length - kprint('==leaving_k:', leaving_k)if leaving_k == 0:return sum(cardPoints)left, right = 0, 0min_res = float('inf')temp_res = 0while right < length:temp_res += cardPoints[right]if right >= leaving_k - 1:min_res = min(min_res, temp_res)print('==temp_res:', temp_res)left += 1temp_res -= cardPoints[left - 1]right += 1print('==min_res:', min_res)return sum(cardPoints) - min_rescardPoints = [1, 2, 3, 4, 5, 6, 1]
k = 3
# cardPoints = [9, 7, 7, 9, 7, 7, 9]
# k = 7
sol = Solution()
sol.maxScore(cardPoints, k)

262.非递减数列

思路:分别从左右两边判断是否递增

class Solution:def checkPossibility(self, nums: List[int]) -> bool:length = len(nums)# res = 0left,right = 0,length-1while left<length-1 and nums[left]<=nums[left+1]:left+=1if left==length-1:return Truewhile right>=0 and nums[right-1]<=nums[right]:right-=1if right - left>1:return Falseif left==0 or right==length-1:return Trueif nums[right+1]>=nums[left] or nums[left-1]<=nums[right]:return Truereturn False

264.最长湍流子数组

思路:双指针

满足山峰:arr[right]>arr[right-1] and arr[right]>arr[right+1]  right+=1

满足山谷:arr[right]

其他时候 left移动到right位置


class Solution:def maxTurbulenceSize(self, arr):left, right = 0, 0length = len(arr)res = 1while right<length-1:if left==right:if left+1<length and arr[left]==arr[left+1]:left+=1right+=1else:#山峰if right+1<length and arr[right]>arr[right-1] and arr[right]>arr[right+1]:right+=1# 山谷elif right+1<length and arr[right]<arr[right-1] and arr[right]<arr[right+1]:right+=1else:left=rightprint('==right:', right)res = max(res, right-left+1)print('==res:', res)return res# arr  = [9,4,2,10,7,8,8,1,9]
# arr = [100]
arr = [2,1]
sol = Solution()
sol.maxTurbulenceSize(arr)


267.数据流中的第 K 大元素

思路1:每个add进去 就sort取第k大,时间复杂度偏大k*log(k),对于这种取topk问题,用最小堆更合适

#k*O(logk)  超时
class KthLargest:def __init__(self, k, nums):self.k = kself.nums = numsdef add(self, val):self.nums.append(val)self.nums = sorted(self.nums)[::-1]return self.nums[self.k - 1]
k = 3
nums = [4, 5, 8, 2]
sol = KthLargest(k, nums)
res = sol.add(3)
print('=res:', res)
res = sol.add(5)
print('=res:', res)
res = sol.add(10)
print('=res:', res)
res = sol.add(9)
print('=res:', res)
res = sol.add(4)
print('=res:', res)

思路2:最小堆,保证最小堆中只有k个元素,那么堆顶自然就是第k大元素

时间复杂度为log(k),因为push和pop都是log(k).

python代码

# 最小堆 topk都用最小堆
import heapq
class KthLargest(object):def __init__(self, k, nums):""":type k: int:type nums: List[int]"""self.k = kself.que = numsheapq.heapify(self.que)def add(self, val):""":type val: int:rtype: int"""heapq.heappush(self.que, val)print('=====self.que====:', self.que)while len(self.que)>self.k:#保持最小堆中只有k个元素 则堆顶就是第k大元素heapq.heappop(self.que)print('clean self.que:', self.que)return self.que[0]k = 3
nums = [4, 5, 8, 2]
sol = KthLargest(k, nums)
res = sol.add(3)
print('=res:', res)
res = sol.add(5)
print('=res:', res)

c++代码:

#include <map>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;class KthLargest {
public:priority_queue<int, vector<int>, greater<int> > que;//最小堆int k;KthLargest(int k, vector<int>& nums) {this->k = k;for(int k=0;k<nums.size();k++){que.push(nums[k]);if (que.size()>this->k){que.pop();}}}int add(int val) {que.push(val);if(que.size()>this->k){que.pop();}return que.top();}
};int main()
{   int k=3;vector<int> nums;nums={4,5,8,2};KthLargest *p = new KthLargest(k, nums);int res = p->add(3);cout<<"res:"<<res<<endl;res = p->add(5);cout<<"res:"<<res<<endl;res = p->add(10);cout<<"res:"<<res<<endl;res = p->add(9);cout<<"res:"<<res<<endl;res = p->add(4);cout<<"res:"<<res<<endl;delete p;p=NULL;return 0;}

269.杨辉三角 II

思路:一层一层遍历出值即可

python代码:

class Solution:def getRow(self, rowIndex: int) -> List[int]:temp = [0]*(rowIndex+1)temp[0] = 1for i in range(1, rowIndex+1):for j in range(i, 0, -1):temp[j] += temp[j-1]# print('==temp:', temp)return temp

c++代码:

#include <map>
#include <vector>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
class Solution {
public:vector<int> getRow(int rowIndex) {vector<int> temp(rowIndex+1, 0);temp[0] = 1;for (int i=1;i<rowIndex+1;i++){for(int j=i;j>0;j--){temp[j]+=temp[j-1];} }return temp;}
};int main()
{   Solution *p = new Solution();int row_index = 3;vector <int> res;res = p->getRow(row_index);for(int k=0;k<res.size();k++){cout<<"res[k]"<<res[k]<<endl;}p=NULL;delete p;return 0;
}

271.找到所有数组中消失的数字

思路1:hash  空间复杂度 o(n) 时间复杂度o(n)

# 空间复杂度 o(n) 时间复杂度o(n)
class Solution:def findDisappearedNumbers(self, nums):dict_={}for i in range(len(nums)):dict_[nums[i]] = dict_.get(nums[i],0)+1res = []for i in range(len(nums)):if i+1 not in dict_:res.append(i+1)print(res)return res

思路2:求出索引在对应位置处 添加长度 如果没有的数字,则数字就小于等于长度

空间复杂度O(1) 时间复杂度O(n)

#空间复杂度O(1) 时间复杂度O(n)
class Solution:def findDisappearedNumbers(self, nums):length = len(nums)for i in range(len(nums)):index= (nums[i]-1)%lengthnums[index] +=lengthprint('==nums:', nums)res = [i+1 for i in range(length) if nums[i] <= length]print(res)return res# nums = [4,3,2,7,8,2,3,1]
nums = [1,2,2,3,3,4,7,8]
# nums = [1,2,3,3,5,6,7]
sol = Solution()
sol.findDisappearedNumbers(nums)

c++代码:

#include <map>
#include <vector>
#include <iostream>
#include <queue>
#include <string>
#include <algorithm>
using namespace std;
class Solution {
public:vector<int> findDisappearedNumbers(vector<int>& nums) {vector<int> res;for (int i=0;i<nums.size();i++){int index = (nums[i]-1)%nums.size();nums[index] += nums.size();}for (int i=0;i<nums.size();i++){if(nums[i]<=nums.size()){res.push_back(i+1);}}return res;}
};int main()
{Solution *p = new Solution();vector <int >nums;nums = {4,3,2,7,8,2,3,1};vector <int> res = p->findDisappearedNumbers(nums);for(int i=0;i<res.size();i++){cout<<"res:"<<res[i]<<endl;    }delete p;p = NULL;return 0;
}

 272.情侣牵手

思路:其实就是将环拆开,0,1都看成第0对,2,3看成第1对

可看出要交换的座位就是环的边数减去1,对于这种去环问题,自然想到并查集

python代码:

class Solution:def find(self,x):if self.parent[x]==x:return xreturn self.find(self.parent[x])def union(self,i,j):#将i的老大变成j的老大self.parent[self.find(i)] = self.find(j)def get_count(self,n):for i in range(n):self.count[self.find(i)]+=1def minSwapsCouples(self, row):n = len(row)//2self.parent = [i for i in range(n)]self.count = [0 for i in range(n)]print('===init self.parent', self.parent)for i in range(0, len(row), 2):self.union(row[i]//2, row[i+1]//2)print('==self.parent:', self.parent)self.get_count(n)print('===self.count:', self.count)res = 0for i in range(n):res += max(self.count[i]-1, 0)print(res)return res# row = [0,2,2]
# row = [0, 2, 1, 3]
# row = [2,0,5,4,3,1]
row = [1,4,0,5,8,7,6,3,2,9]
# row = [0, 1, 2, 3]
sol = Solution()
sol.minSwapsCouples(row)

c++代码:

#include <map>
#include <vector>
#include <iostream>
#include <queue>
#include <string>
#include <algorithm>
using namespace std;class Solution {
public:vector<int> parent;vector<int> count;int find(int x){if(x==parent[x]){return x;}return find(parent[x]);}//把i的老大换成j的老大void merge(int i, int j){parent[find(i)]=find(j);}void get_count(int n){for (int i=0;i<n;i++){   count[find(i)]+=1;}}int minSwapsCouples(vector<int>& row) {int n = row.size()/2;cout<<n<<endl;int res=0;for(int i=0;i<n;i++){parent.push_back(i);count.push_back(0);}for(int i=0;i<row.size();i+=2){merge(row[i]/2,row[i+1]/2);}get_count(n);// // //debug // for (int i=0;i<parent.size();i++)// {//     cout<<"===parent[i]"<<parent[i]<<endl;// }//debug // for (int i=0;i<count.size();i++)// {//     cout<<"===count[i]"<<count[i]<<endl;// }for (int i=0;i<count.size();i++){res+=max(count[i]-1,0);}return res;}
};
int main()
{Solution *p = new Solution();vector<int> row;row = {0, 2, 1, 3};int res = p->minSwapsCouples(row);cout<<"==res:"<<res<<endl;delete p;p=NULL;return 0;
}

273.最大连续1的个数

思路1:直接数1个数

class Solution:def findMaxConsecutiveOnes(self, nums):count_one = 0res = 0for i in range(len(nums)):if nums[i]==1:count_one+=1else:count_one=0res = max(res, count_one)# print(res)return res

思路2:dp

class Solution:def findMaxConsecutiveOnes(self, nums):res = [-1]for i in range(len(nums)):if nums[i]==0:res.append(i)res.append(len(nums))print(res)if len(res)==1:return res[-1]max_length = 0for i in range(1, len(res)):max_length = max(res[i]-res[i-1]-1, max_length)print(max_length)return max_length

思路3:双指针滑动窗口

class Solution:def findMaxConsecutiveOnes(self, nums):left,right=0,0res = 0while right<len(nums):if nums[right]==1:right+=1else:right+=1left=rightprint('==left,right:', left, right)res = max(res, right - left)print('==res:', res)return res

c++双指针:

#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;class Solution {
public:int findMaxConsecutiveOnes(vector<int>& nums) {int left=0;int right = 0;int res = 0;while (right<nums.size()){if(nums[right]==1){right++;}else{                   right++;left=right;                }res = max(right-left, res);}return res;        }
};int main()
{Solution *p = new Solution();vector<int> nums;nums = {1,1,0,1,1,1};int res = p->findMaxConsecutiveOnes(nums);cout<<"==res:"<<res<<endl;delete p;p=NULL;return 0;
}

274.重塑矩阵

思路:对于h*w的元素个数,索引为h_index = i//rows,w_index = i%rows

python代码

class Solution:def matrixReshape(self, nums: List[List[int]], r: int, c: int) -> List[List[int]]:h = len(nums)w = len(nums[0])if h*w != r*c:return numsres = [[0 for _ in range(c)] for _ in range(r)]# print(res)for i in range(h*w):res[i//c][i%c] = nums[i//w][i%w]# print(res)return res

c++代码:

class Solution {
public:vector<vector<int>> matrixReshape(vector<vector<int>>& nums, int r, int c) {int h = nums.size();int w = nums[0].size();// cout<<"==h:"<<h<<endl;vector<vector<int>> res(r ,vector<int>(c,0));  //初始化c*r元素为0的矩阵 // cout<<"==res.size():"<<res.size()<<endl;// cout<<"==res[0].size():"<<res[0].size()<<endl;if(h*w!=r*c){return nums;}for (int i=0;i<h*w;i++){   // cout<<"i/w:"<<i/w<<endl;// cout<<"i%w:"<<i%w<<endl;res[i/c][i%c] = nums[i/w][i%w];}return res;}
};

275.最大连续1的个数 III

思路:其实就是滑动窗口判断有大于K个0的则左指针右移动,之所以用大于K来判断是因为0后续可能会跟着很多1,所以大于K的话,会把这些包含进去,和https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 思想一样

python:

class Solution:def longestOnes(self, A: List[int], K: int) -> int:left,right =0,0n = len(A)zero_count =0res = 0while right<n:if A[right]==0:zero_count+=1#left向右收缩while zero_count>K:#大于K个0的时候就说明找到符合条件的了if A[left]==0:zero_count-=1left+=1res = max(res, right - left + 1)# print('=left:', left)# print('==right:', right)# print('==res:', res)right+=1# print(res)return res

c++

class Solution {
public:int longestOnes(vector<int>& A, int K) {int left=0;int right =0;int res=0;int zero_count =0;int length = A.size();while(right<length){   if (A[right]==0){zero_count++;}while (zero_count>K){   if (A[left]==0){zero_count--;}left++;}res = max(res, right-left+1);right++;}return res;}
};

276.数组的度

思路:三个hash,一个计度,一个记录左索引,一个记录右索引

python:

class Solution:def findShortestSubArray(self, nums: List[int]) -> int:dict_ = {}left_index_dict = {}right_index_dict = {}for i in range(len(nums)):dict_[nums[i]] = dict_.get(nums[i], 0)+1if nums[i] not in left_index_dict:left_index_dict[nums[i]] = iright_index_dict[nums[i]] = i# print('==dict_:', dict_)# print('=left_index_dict:', left_index_dict)# print('==right_index_dict:', right_index_dict)dict_ = dict(sorted(dict_.items(), key=lambda x:x[1],reverse=True))# print(dict_)max_degree = 0res = float('inf')for key,value in dict_.items():max_degree = valuebreak# print(max_degree)for key, value in dict_.items():if value==max_degree:res = min(res, right_index_dict[key] - left_index_dict[key]+1)# print('===res:',res)return res

c++:

class Solution {
public:int findShortestSubArray(vector<int>& nums) {map<int, int>dict_;map<int, int>left_index_dict;map<int, int>right_index_dict;for(int i=0;i<nums.size();i++){dict_[nums[i]]++;if(left_index_dict.count(nums[i])==0){left_index_dict[nums[i]] = i;}right_index_dict[nums[i]] = i;}int max_degree=0;map<int,int>::iterator iter=dict_.begin();for (;iter!=dict_.end();iter++){max_degree = max(max_degree, iter->second);}int res=INT_MAX;map<int,int>::iterator iter_2=dict_.begin();for (;iter_2!=dict_.end();iter_2++){if (max_degree == iter_2->second){res = min(res, right_index_dict[iter_2->first] - left_index_dict[iter_2->first]+1);}}return res;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/493128.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在ubuntu 12.04 x64下编译hadoop2.4

自己编译hadoop&#xff1a;x64 1.安装依赖包 sudo apt-get install g autoconf automake libtool cmake zlib1g-dev pkg-config libssl-dev openssh-server maven openssh-client 2.下载hadoop源码 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.4.0/hadoop…

中科院脑科学与智能技术卓越创新中心:在“脑海”中突破进取

来源&#xff1a;中国科学报 2017年底&#xff0c;“中中”和“华华”两个可爱的小猴子降临人世&#xff0c;标志着中国率先开启了以体细胞克隆猴作为实验动物模型的新时代。这是继2016年建立食蟹猴自闭症模型后&#xff0c;中科院脑科学与智能技术卓越创新中心再一次取得非人灵…

python(c++)刷题+剑指offer

03. 数组中重复的数字 思路:hash class Solution:def findRepeatNumber(self, nums: List[int]) -> int:dict_ dict()for i in range(len(nums)):if nums[i] in dict_:return nums[i]else:dict_[nums[i]] i class Solution { public:int findRepeatNumber(vector<int…

erlang开发环境配置

第一步 从源码安装erlang git clone https://github.com/erlang/otp 目前最新版本为17.X cd otp/ ./configer 检查编译环境 sudo make & make install 编译并安装 我是在ubuntu 系统下配置的 其余的linux 环境我是直接切换到root用户操作 这样安装需要自己一个一个解决…

美国免费为全世界提供GPS服务,为什么中国还要搞“北斗”?

来源&#xff1a;雷锋网摘要&#xff1a;12月27日&#xff0c;在国务院新闻办公室新闻发布会上&#xff0c;中国卫星导航系统管理办公室主任、北斗卫星导航系统新闻发言人冉承其宣布——北斗三号基本系统完成建设&#xff0c;于今日开始提供全球服务。这标志着北斗系统服务范围…

IDC与百度联合发报告:预测2019年人工智能十大趋势

来源&#xff1a;网络大数据12月20日&#xff0c;国际数据公司(IDC)与百度AI产业研究中心(BACC)联合发布《百度大脑领导力白皮书》&#xff0c;白皮书预测了2019年中国人工智能市场发展趋势&#xff0c;通过实际案例解析人工智能如何从技术到落地&#xff0c;并提出“100天AI部…

链表的一些leetcode题目+python(c++)

主要常见下面几个知识点: 1-1.请编写一个函数&#xff0c;使其可以删除某个链表中给定的&#xff08;非末尾&#xff09;节点&#xff0c;你将只被给定要求被删除的节点。 python: # Definition for singly-linked list. # class ListNode: # def __init__(self, x): # …

暑训day1解题报告

A - Painting the sticks因为不能覆盖涂/涂两次&#xff0c;所以就数数有几个三个一块儿就行了。#include<cstdio> int a[100],ans ; int main() {int n , t 0 ;while (scanf("%d",&n)!EOF) {for (int i1; i<n; i) scanf("%d",ai);ans 0 ; …

2019展望:超级智能崛起,人类智慧与机器智能将深度融合

作者&#xff1a;刘锋 计算机博士 互联网进化论作者摘要&#xff1a;在2019年到来的脚步声中&#xff0c;感觉要写点文字&#xff0c;对2019年的科技趋势进行展望&#xff0c;也算是对2018年思考的总结&#xff0c;这篇展望的文章主要表达经过50年的科技和商业拉动&#xff0c;…

二叉树的一些leetcode题目+python(c++)

二叉树考点主要有: 1.三种遍历方式,以及构造二叉树等&#xff1b; 2.求深度,最长直径&#xff0c;最长路径,公共祖先等等; 3.合并二叉树&#xff0c;翻转二叉树&#xff0c;判断平衡性,对称性等; 4.从前序与中序构造二叉树&#xff0c;中序与后序构造二叉树&#xff0c;二叉…

Eclipse下如何导入jar包

原地址&#xff1a;http://blog.csdn.net/justinavril/article/details/2783182 我们在用Eclipse开发程序的时候&#xff0c;经常想要用到第三方的jar包。这时候我们就需要在相应的工程下面导入这个jar包。以下配图说明导入jar包的步骤。 1.右击工程的根目录&#xff0c;点击Pr…

面对“超人革命”,我们是否已做好准备?

来源&#xff1a;资本实验室人类自诞生以来&#xff0c;就一直处在自然规律的支配之下。但自从第一次制造工具并学会使用火的那一刻起&#xff0c;人类就开始走在了持续摆脱大自然生物束缚的道路上。千里听音、力大无穷、不死之身、翱翔天际、深入大洋……各种神话中无需借助外…

RepVGG

论文链接 一.背景: 现在的一些复杂模型虽然有很高准确度,但是缺点也很明显: 1.多分支,带来了速度的减慢和降低显存的使用率; 2.Mobilenet虽然采用可分离卷积.shufflenet采用分组卷积,带来了flop降低,但是却增加了内存的访问成本(MAC) 二.网络结构 1. 模型 RepVGG在train和…

2018十大科技丑闻,连娱乐圈都甘拜下风

来源&#xff1a;科技日报这一年里&#xff0c;风起云涌的科技界很忙有些人尝到了甜头有些人却吃到了苦头有些事件令人瞠目结舌、难以置信“404”教授梁莹120篇论文凭空蒸发韩春雨论文调查结果被吐槽酸碱体质论与心脏干细胞的创始人双双走下神坛日本福岛核电站污水处理报告错误…

华为究竟做了多少芯片?

来源&#xff1a;半导体行业观察华为依托于旗下的海思大举进军芯片的这个事实已经广为人知了。除了Kirin芯片外&#xff0c;华为在IPC视频编解码和图像信号处理的芯片、电视芯片&#xff0c;Balong基带和NB-IoT芯片等多个领域都取得不错的市场表现&#xff0c;也获得了大家的高…

leetcode hot100(第一部分) + python(c++)

1-1.两数之和 思路&#xff11;&#xff1a;两层for循环 &#xff2f;&#xff08;&#xff4e;2&#xff09; class Solution:def twoSum(self, nums, target):res []for i in range(len(nums)):for j in range(i1, len(nums)):if nums[i]nums[j]target:res.extend([i, j])b…

云计算深度报告:算力时代迎巨变

来源&#xff1a;中泰证券云计算正进入算力时代供给端:数据存量增长与计算成本下降推动算力需求增长信息技术快速发展与传统产业数据化转型带来大量数据存量。随着云计算、大数据、物联网、人工智能等信息技术的快速发展和传统产业数字化的转型&#xff0c;数据量呈现几何级增长…

c++将.cpp编译为.so文件

1.首先看文件形式 其中cpp1是直接调用.cpp和生成.so的文件夹。 cpp2是测试生成的.so可以使用的文件夹。 2.先直接编译.cpp检查代码没问题 a.cpp内容: #include <iostream> #include "a.h"void A::readImg(char* path) {B b;b.readImg(path);} a.h内容: …

vscode debug c++与opencv程序

一.工程代码 1.本文调试代码文件夹截图为: 2.代码细节: a.h: #ifndef A_H_ #define A_H_class A {public:A(){}~A(){}void readImg(const char* path);};#endif a.cpp: #include<opencv2/opencv.hpp> #include <iostream> #include "a.h"using name…

回顾 | 2018年十大AI新闻 中国继续占据主导优势

来源&#xff1a;网易智能摘要&#xff1a;普华永道&#xff08;PwC&#xff09;估计&#xff0c;到2030年&#xff0c;AI领域的发展将为全球经济贡献15.7万亿美元。本次评选出2018年十大AI新闻&#xff0c;它们囊括各个领域&#xff0c;有好有坏&#xff0c;从AI突破和新投资&…