【LeetCode】第三次总结。

计划对LeetCode刷题,顺便总结一下,四个阶段:

  1. 找出典型中等、困难题目,走读题目根据自己还记得的算法尝试回忆一遍
  2. 对照答案,识别自己的算法弱项,巩固算法后练习一遍典型习题
  3. 尝试找出同类型题目,巩固练习一遍
  4. 找出算法短板,重复1/2/3

算法总结

题目我的算法典型算法
二叉树的最大宽度BFS遍历一次二叉树,遍历过程中判断是否影响最大宽度
节点间通路递归实现,将graph信息转化为map<N, M[…]>,即从N点出发可以到的M[…]集合点
阈值距离内邻居最少的城市BFS,计算每个城市到其他城市在阈值范围内的个数,然后进行排序比对,选出城市最少,编号最大的城市。Floyd算法(动态规划的一种)
计算器通过入栈出栈和运算符优先级比较完成表达式解析运算用栈
下一个更大元素和之前做过的题目思路相同,只不过将帧数拆分为数字而已
数组中两个数的最大异或值暴力解法
多次搜索暴力解法
尽可能使字符串相等滑动窗口滑动窗口
绝对差不超过限制的最长连续数组滑动窗口滑动窗口
扫雷游戏BFSBFS
最短的桥BFS+DFSBFS+DFS
最大矩形暂无思路单调栈
活字印刷DFS回溯DFS
在D天内送达包裹的能力二分查找二分查找
元素和小于等于阈值的正方形最大边长二分查找二分查找 + 前缀和
每日温度暴力解法单调栈
下一个更大的元素2暴力解法单调栈
朋友圈并查集并查集,DFS/BFS也是可以的
尽量减少恶意软件传播并查集的优化

二叉树的最大宽度

链接:https://leetcode-cn.com/problems/maximum-width-of-binary-tree

给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空。

每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。

示例 1:

输入:

       1
     /   \
    3     2
   / \     \  
  5   3     9 

输出: 4
解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。
示例 2:

输入:

      1
     /  
    3    
   / \       
  5   3     

输出: 2
解释: 最大值出现在树的第 3 层,宽度为 2 (5,3)。
示例 3:

输入:

      1
     / \
    3   2 
   /        
  5      

输出: 2
解释: 最大值出现在树的第 2 层,宽度为 2 (3,2)。
示例 4:

输入:

      1
     / \
    3   2
   /     \  
  5       9 
 /         \
6           7

输出: 8
解释: 最大值出现在树的第 4 层,宽度为 8 (6,null,null,null,null,null,null,7)。

思路:遍历一次二叉树,遍历过程中判断是否影响最大宽度
1、影响宽度的因素有两种,最左树的左节点不为空、最右树的有节点不为空,此时宽度+1
2、遍历过程时刻记录最左左右两个节点,当遍历这两个节点时进行判断
a.初始宽度width=1
b.left = right = root
c.BFS遍历树
d.如果左子树不为空,且父节点是left,left = node.left,width++;
e.如果右子树不为空,且父节点是right,right = node.right,width++;
e.如果当前节点是空,return
3、计算得出width

节点间通路

链接:https://leetcode-cn.com/problems/route-between-nodes-lcci

节点间通路。给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。

示例1:

输入:n = 3, graph = [[0, 1], [0, 2], [1, 2], [1, 2]], start = 0, target = 2
输出:true
示例2:

输入:n = 5, graph = [[0, 1], [0, 2], [0, 4], [0, 4], [0, 1], [1, 3], [1, 4], [1, 3], [2, 3], [3, 4]], start = 0, target = 4
输出 true
提示:

节点数量n在[0, 1e5]范围内。
节点编号大于等于 0 小于 n。
图中可能存在自环和平行边。

思路:递归实现,将graph信息转化为map<N, M[…]>,即从N点出发可以到的M[…]集合点
1、从start点出发,获得M,遍历M
2、当M中任意一个为target,返回true
3、如果M中节点不是target,则递归调用,直到找到target

阈值距离内邻居最少的城市

链接:https://leetcode-cn.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance

有 n 个城市,按从 0 到 n-1 编号。给你一个边数组 edges,其中 edges[i] = [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边,距离阈值是一个整数 distanceThreshold。

返回能通过某些路径到达其他城市数目最少、且路径距离 最大 为 distanceThreshold 的城市。如果有多个这样的城市,则返回编号最大的城市。

注意,连接城市 i 和 j 的路径的距离等于沿该路径的所有边的权重之和。

示例 1:
输入:n = 4, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]], distanceThreshold = 4
输出:3
解释:城市分布图如上。
每个城市阈值距离 distanceThreshold = 4 内的邻居城市分别是:
城市 0 -> [城市 1, 城市 2]
城市 1 -> [城市 0, 城市 2, 城市 3]
城市 2 -> [城市 0, 城市 1, 城市 3]
城市 3 -> [城市 1, 城市 2]
城市 0 和 3 在阈值距离 4 以内都有 2 个邻居城市,但是我们必须返回城市 3,因为它的编号最大。
示例 2:

输入:n = 5, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]], distanceThreshold = 2
输出:0
解释:城市分布图如上。
每个城市阈值距离 distanceThreshold = 2 内的邻居城市分别是:
城市 0 -> [城市 1]
城市 1 -> [城市 0, 城市 4]
城市 2 -> [城市 3, 城市 4]
城市 3 -> [城市 2, 城市 4]
城市 4 -> [城市 1, 城市 2, 城市 3]
城市 0 在阈值距离 4 以内只有 1 个邻居城市。

思路:BFS,计算每个城市到其他城市在阈值范围内的个数,然后进行排序比对,选出城市最少,编号最大的城市。

计算器

连接:https://leetcode-cn.com/problems/calculator-lcci/

给定一个包含正整数、加(+)、减(-)、乘(*)、除(/)的算数表达式(括号除外),计算其结果。

表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。

示例 1:

输入: “3+2*2”
输出: 7
示例 2:

输入: " 3/2 "
输出: 1
示例 3:

输入: " 3+5 / 2 "
输出: 5

思路,用栈,基于运算符优先级判断是否弹栈并计算
1、第一个元素入栈
2、遍历每个元素
3、当前元素不是运算符,入栈,continue
4、当前元素是运算符,lastOperator == null,入栈,continue
5、当前元素是预算福或者已经到了最后一个元素,lastOperator != NULL ,判断优先级
a. 当前优先级低(或者最后一个元素),出栈,直到遇到运算符,形成第二个预算数;继续出栈,直到遇到运算符或者栈空,形成第一个运算数;完成运算,入栈
b. 当前优先级高,入栈,continue

下一个更大元素|||

链接:https://leetcode-cn.com/problems/next-greater-element-iii

给定一个32位正整数 n,你需要找到最小的32位整数,其与 n 中存在的位数完全相同,并且其值大于n。如果不存在这样的32位整数,则返回-1。

示例 1:

输入: 12
输出: 21
示例 2:

输入: 21
输出: -1

思路:和之前做过的题一样,上次是一个数组,里面有一些数字,然后按照找出最小的比当前数值大的数组,其实将本题拆开后和上次的那个题就差不多了。
上次一开始的思路是,从右边开始找出第一个降序的两个相邻的两个元素,降序的两个元素思路没错,问题在于这两个元素不一定相邻,所以的分开找。

数组中两个数的最大异或值

链接:https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array

给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 。

找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i, j < n 。

你能在O(n)的时间解决这个问题吗?

示例:

输入: [3, 10, 5, 25, 2, 8]

输出: 28

解释: 最大的结果是 5 ^ 25 = 28.

思路:暴力破解,两次循环,计算出任意两个元素的异或值 ,然后求出最大的异或结果

多次搜索

链接:https://leetcode-cn.com/problems/multi-search-lcci

给定一个较长字符串big和一个包含较短字符串的数组smalls,设计一个方法,根据smalls中的每一个较短字符串,对big进行搜索。输出smalls中的字符串在big里出现的所有位置positions,其中positions[i]为smalls[i]出现的所有位置。

示例:
输入:
big = “mississippi”
smalls = [“is”,“ppi”,“hi”,“sis”,“i”,“ssippi”]
输出: [[1,4],[8],[],[3],[1,4,7,10],[5]]

思路:暴力破解,挨个从big中用indexOf去判断small求出结果
解题结果:内存超出限制

尽可能使字符串相等

链接:https://leetcode-cn.com/problems/get-equal-substrings-within-budget

给你两个长度相同的字符串,s 和 t。
将 s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。
用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。
如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。
如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0。

示例 1:
输入:s = “abcd”, t = “bcdf”, cost = 3
输出:3
解释:s 中的 “abc” 可以变为 “bcd”。开销为 3,所以最大长度为 3。
示例 2:
输入:s = “abcd”, t = “cdef”, cost = 3
输出:1
解释:s 中的任一字符要想变成 t 中对应的字符,其开销都是 2。因此,最大长度为 1。
示例 3:
输入:s = “abcd”, t = “acde”, cost = 0
输出:1
解释:你无法作出任何改动,所以最大长度为 1。

思路:滑动窗口
1、left = right = 0
2、maxLen = 0
3、right++,计算s[right] - t[right],判断是否在cost内
4、如果满足cost,则通过right - left 更新maxLen
5、如果不满足cost,则left++,同时恢复s[left] - t[left]
6、直到right == s.length-1
7、计算出maxLen
解题结果:提交4次AC
1、变量名写错耽误了点时间
2、对于s[left] - t[left]应该是最左端的,也写错了,写成了上一次的了
3、当发现cost不满足的时候,此时除了恢复之外,right不用++,因为此时可能就算移动了left,cost也是不满足的

绝对差不超过限制的最长连续数组

链接:https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit

给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。

如果不存在满足条件的子数组,则返回 0 。

示例 1:

输入:nums = [8,2,4,7], limit = 4
输出:2
解释:所有子数组如下:
[8] 最大绝对差 |8-8| = 0 <= 4.
[8,2] 最大绝对差 |8-2| = 6 > 4.
[8,2,4] 最大绝对差 |8-2| = 6 > 4.
[8,2,4,7] 最大绝对差 |8-2| = 6 > 4.
[2] 最大绝对差 |2-2| = 0 <= 4.
[2,4] 最大绝对差 |2-4| = 2 <= 4.
[2,4,7] 最大绝对差 |2-7| = 5 > 4.
[4] 最大绝对差 |4-4| = 0 <= 4.
[4,7] 最大绝对差 |4-7| = 3 <= 4.
[7] 最大绝对差 |7-7| = 0 <= 4.
因此,满足题意的最长子数组的长度为 2 。
示例 2:

输入:nums = [10,1,2,4,7,2], limit = 5
输出:4
解释:满足题意的最长子数组是 [2,4,7,2],其最大绝对差 |2-7| = 5 <= 5 。
示例 3:

输入:nums = [4,2,2,2,4,4,2,2], limit = 0
输出:3

思路:滑动窗口
1、left = right = 0
2、maxLen = 0
3、minIndex = maxIndex = 0,用来记录当前最大最小值的索引位置
4、每次循环对minIndex、maxIndex先更新
5、用当前元素和max、min计算abs看是否满足要求
6、如果满足要求,right++
7、如果不满足要求,分两种情况:
a. right当前值比max大,left=minindex+1,同时重新计算left ~ right之间的minindex
b. right当前值比min小,left=maxIndex+1,同时重新计算left ~ right之间的maxindex
解题结果:5次提交AC
1、仍然出现了低级的笔误,导致定位
2、开始思考的时候仅仅记录了maxValue和minValue,而不是index
3、在阈值不满足的情况下,left的选择和right是否++出现了问题,没思考很清楚,没有思考到要判断right当前元素分两种情况

扫雷游戏

链接:https://leetcode-cn.com/problems/minesweeper

让我们一起来玩扫雷游戏!

给定一个代表游戏板的二维字符矩阵。 ‘M’ 代表一个未挖出的地雷,‘E’ 代表一个未挖出的空方块,‘B’ 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字(‘1’ 到 ‘8’)表示有多少地雷与这块已挖出的方块相邻,‘X’ 则表示一个已挖出的地雷。

现在给出在所有未挖出的方块中(‘M’或者’E’)的下一个点击位置(行和列索引),根据以下规则,返回相应位置被点击后对应的面板:

如果一个地雷(‘M’)被挖出,游戏就结束了- 把它改为 ‘X’。
如果一个没有相邻地雷的空方块(‘E’)被挖出,修改它为(‘B’),并且所有和其相邻的未挖出方块都应该被递归地揭露。
如果一个至少与一个地雷相邻的空方块(‘E’)被挖出,修改它为数字(‘1’到’8’),表示相邻地雷的数量。
如果在此次点击中,若无更多方块可被揭露,则返回面板。

示例 1:
输入:
[[‘E’, ‘E’, ‘E’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘M’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘E’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘E’, ‘E’, ‘E’]]
Click : [3,0]

输出:

[[‘B’, ‘1’, ‘E’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘M’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘1’, ‘1’, ‘B’],
[‘B’, ‘B’, ‘B’, ‘B’, ‘B’]]
解释:
示例 2:

输入:

[[‘B’, ‘1’, ‘E’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘M’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘1’, ‘1’, ‘B’],
[‘B’, ‘B’, ‘B’, ‘B’, ‘B’]]

Click : [1,2]
输出:
[[‘B’, ‘1’, ‘E’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘X’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘1’, ‘1’, ‘B’],
[‘B’, ‘B’, ‘B’, ‘B’, ‘B’]]
解释:

注意:
输入矩阵的宽和高的范围为 [1,50]。
点击的位置只能是未被挖出的方块 (‘M’ 或者 ‘E’),这也意味着面板至少包含一个可点击的方块。
输入面板不会是游戏结束的状态(即有地雷已被挖出)。
简单起见,未提及的规则在这个问题中可被忽略。例如,当游戏结束时你不需要挖出所有地雷,考虑所有你可能赢得游戏或标记方块的情况。

思路:BFS,从给定的点开始BFS,根据题目中给出的条件逐个标记,其中题目有个点需要仔细审审:只有当一个点被标记为B时,才揭露它周围的点;如果一个B点揭露了周围的点,并且标记为数字,那么这些数字点并不会揭露其周围的点
1、从起点开始遍历,将出发点push到queue中
2、循环遍历queue,当不为空时,判断当前点属于以下哪种情况
a. 当前点是E,则将该点标记为B,然后push到队列中
b. 当前点是B,说明已经揭露了,B点的处理办法是揭露周围8个点,并且将他们push到queue中
c. 当前点是数字,说明已经揭露了,数字点的处理办法是跳过
d. 当前点是M,说明是个雷,雷的处理办法是跳过
e.当前点是X,踩雷了,跳出循环,游戏结束
3、完成对queue的遍历
解题结果:提交2次AC
1、揭露一个点时需要知道周围8个点的情况,在上下左右那里写错了,修改后AC

最短的桥

链接:https://leetcode-cn.com/problems/shortest-bridge

在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)

现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。

返回必须翻转的 0 的最小数目。(可以保证答案至少是 1。)

示例 1:

输入:[[0,1],[1,0]]
输出:1
示例 2:

输入:[[0,1,0],[0,0,0],[0,0,1]]
输出:2
示例 3:

输入:[[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
输出:1

思路:BFS+DFS,真没啥好办法,DFS先标出其中一座岛屿,BFS从这个已知岛屿出发找到另一座到的最短距离。
DFS:
1、设置一个标记矩阵visited[][]来表示是否访问过,设置一个island[][]来表示其中一座岛屿
2、随便找到一个为1的元素,从这个元素开始DFS
3、DFS(x,y)
a. 标记visited[x][y] = 1
b. 标记island[x][y] = 1
c. 通过上下左右分别DFS四个点
d. 如果任意一个点已经visited[][] == 1,则直接return
e. 如果任意一个点A[][]并不是岛屿,则直接return
经过上述DFS,已经标识出其中一个岛屿,并在island中记录,此时island和visited保持一致;
BFS:
1、思路是从已知岛屿的所有点BFS,每遍历一次,则将path++,直到找到另一座岛屿,思路和单个点逐个BFS/DFS然后比对路径大小要快一些。
1、定义minPath
2、将所有island的点全部push到queue中
3、遍历queue
a. 如果当前点是1
----aa.属于本岛,则将上下左右的四个为0的点push到queue中,同时当前点island[][] = 1;
----ab.属于本岛,在上下左右遍历过程中发现另一个岛屿,说明找到了,return minPath
b.如果当前点是0
a.说明从本岛已经向外扩散了一圈了,此时要讲这一圈0全部消耗掉,具体做法是,从queue中poll出所有点,如果是对应A[][]是0,则将对应的A[][]=1,同时island[][]=1,再push到queue中;如果是对应A[][]是1就直接丢掉;同时minPath++;
解题过程:提交2次AC
1、DFS还好,BFS花了点时间
2、BFS出现问题一,计算错误,多计算了一次广播,因为每次发现0的时候,都要进行一次minPath++,开始的做法是当发现是1并且不是本岛,把1放入了queue中,但又不能保证下次从queue中取的时候,能第一个取到这个1,如果前面有0,和1是一次广播的结果,那么就会对0进行计算,minPath就会比正常情况下大1
3、BFS出现的问题二,性能问题,每次发现0,将0全部变成1之后,原先队列里的1其实可以不用了,因为都是基于最外层的1进行BFS的,所以仅仅需要把最外成的0变成1,然后插入队列,原先队列的1没有意义了。

最大矩形

链接:https://leetcode-cn.com/problems/maximal-rectangle

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例 1:

输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:6
解释:最大矩形如上图所示。
示例 2:

输入:matrix = []
输出:0
示例 3:

输入:matrix = [[“0”]]
输出:0
示例 4:

输入:matrix = [[“1”]]
输出:1
示例 5:

输入:matrix = [[“0”,“0”]]
输出:0

思路:单调栈

活字印刷

链接:https://leetcode-cn.com/problems/letter-tile-possibilities

你有一套活字字模 tiles,其中每个字模上都刻有一个字母 tiles[i]。返回你可以印出的非空字母序列的数目。

注意:本题中,每个活字字模只能使用一次。

示例 1:

输入:“AAB”
输出:8
解释:可能的序列为 “A”, “B”, “AA”, “AB”, “BA”, “AAB”, “ABA”, “BAA”。
示例 2:

输入:“AAABBC”
输出:188

思路:DFS求路径总数的问题,将字符串中的每个字符当成一个节点,从任意节点(不重复的,比如有两个A,那么A就只当成一次)出发DFS获得结果
1、为了解决重复出发的问题,假设从1~26个字母挨个遍历计算
2、根据字符串计算出每个元素出现的个数
3、定一个totalCount = 0
4、遍历26个字母,如果发现当前字母可用,那就totalCount++,并将当前字母可用数-1,然后DFS减1后的集合;
5、如果发现当前字母不可用,说明没法继续下去,返回0
本题用到了回溯,回溯和DFS的区别在于回溯会会有条件补充,在DFS下一个节点后,会根据条件补偿回来,而DFS是一种只负责遍历的算法

在D天内送达包裹的能力

链接:https://leetcode-cn.com/problems/capacity-to-ship-packages-within-d-days

传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。

传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。

返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力。

示例 1:

输入:weights = [1,2,3,4,5,6,7,8,9,10], D = 5
输出:15
解释:
船舶最低载重 15 就能够在 5 天内送达所有包裹,如下所示:
第 1 天:1, 2, 3, 4, 5
第 2 天:6, 7
第 3 天:8
第 4 天:9
第 5 天:10

请注意,货物必须按照给定的顺序装运,因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。
示例 2:

输入:weights = [3,2,2,4,1,4], D = 3
输出:6
解释:
船舶最低载重 6 就能够在 3 天内送达所有包裹,如下所示:
第 1 天:3, 2
第 2 天:2, 4
第 3 天:1, 4
示例 3:

输入:weights = [1,2,3,1,1], D = 4
输出:3
解释:
第 1 天:1
第 2 天:2
第 3 天:3
第 4 天:1, 1

思路:二分查找,船在满足D的情况下,最小承载量,从题目中可知,承载量最小值就是货物最多的一次,最大值就是全部货物的重量,无非就是在这两个边界之间找到最小的满足条件的船承重
1、求出数组中的最大和总量
2、minWeight = 最大值;maxWeight = 总重量
3、当minWeight <= maxWeight时
4、weight = (minWeight + maxWeight)/2
5、判断weight是否满足要求
a.满足,说明可以尝试更小的承重,maxWeight = weight - 1(-1的原因是,当前weight肯定是能满足的,所以要尝试更小)
b.不满足,说明要常会更大的承重,minWeight = weight + 1(-1的原因是,当前weight肯定是不能满足的,所以要尝试更大)
6、最终得出weight
解题过程:2次提交AC
1、问题在于理论上应该返回的是weight,但是没搞明白为啥,需要返回的是minWeight

元素和小于等于阈值的正方形最大边长

链接:https://leetcode-cn.com/problems/maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold

给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold。

请你返回元素总和小于或等于阈值的正方形区域的最大边长;如果没有这样的正方形区域,则返回 0 。

示例 1:

输入:mat = [[1,1,3,2,4,3,2],[1,1,3,2,4,3,2],[1,1,3,2,4,3,2]], threshold = 4
输出:2
解释:总和小于 4 的正方形的最大边长为 2,如图所示。
示例 2:

输入:mat = [[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2]], threshold = 1
输出:0
示例 3:

输入:mat = [[1,1,1,1],[1,0,0,0],[1,0,0,0],[1,0,0,0]], threshold = 6
输出:3
示例 4:

输入:mat = [[18,70],[61,1],[25,85],[14,40],[11,96],[97,96],[63,45]], threshold = 40184
输出:2

思路:二分查找,题目要求的是最大边长,边长肯定是在0~矩形短边之间的一个值,因此只需要通过二分查找找出最大的边长即可。这里是否满足阈值,可以用暴力方法来实现,更好的一种是前缀和,通过前缀和可以On的求出任意一个举行的权值。
二分查找的思路就不行赘述了,主要是前缀和,核心的逻辑是:
1、声明一个比原有举行大1的举行P[mat.length+1][mat[0].length+1]
2、P这个数组最终的P[i][j]代表了从P[1][1]为左上角,P[i][j]为右下角的矩形的权值之和
3、通过两个for循环,i=j=1遍历计算,P[i][j] = P[i][j-1]+P[i-1][j]-P[i-][j-1] + mat[i-1][j-1]
4、上述mat[i-1][j-1]减1的原因是,mat数组是比P[][]要小1的,所以P在计算<i,j>坐标时,其实对应到mat的计算对象就是<i-1,j-1>
5、任意一个矩形的面积就可以从国左上角和右下角两个点来确定:
左上角:x1,y1
右下角:x2,y2
area = P[x2][y2] - P[x2][y1-1] - P[x2-1][y1] + P[x1-1][y1-1]

每日温度

链接:https://leetcode-cn.com/problems/daily-temperatures

请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

思路:暴力解法,挨个计算出每个元素的下一个比它大的位置并记录

下一个更大的元素||

链接:https://leetcode-cn.com/problems/next-greater-element-ii

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

示例 1:

输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

思路:暴力解法,挨个计算出每个元素的下一个比它大的位置并记录

朋友圈

链接:https://leetcode-cn.com/problems/friend-circles

班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

示例 1:

输入:
[[1,1,0],
[1,1,0],
[0,0,1]]
输出:2
解释:已知学生 0 和学生 1 互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回 2 。
示例 2:

输入:
[[1,1,0],
[1,1,1],
[0,1,1]]
输出:1
解释:已知学生 0 和学生 1 互为朋友,学生 1 和学生 2 互为朋友,所以学生 0 和学生 2 也是朋友,所以他们三个在一个朋友圈,返回 1 。

思路:并查集,完成任意两个学生之间的union,然后得出parent[I] == -1的个数,-1代表根节点,即代表了朋友圈的个数,除此之外,本题还可以通过DFS/BFS实现

尽量减少恶意软件传播

链接:https://leetcode-cn.com/problems/minimize-malware-spread

在节点网络中,只有当 graph[i][j] = 1 时,每个节点 i 能够直接连接到另一个节点 j。

一些节点 initial 最初被恶意软件感染。只要两个节点直接连接,且其中至少一个节点受到恶意软件的感染,那么两个节点都将被恶意软件感染。这种恶意软件的传播将继续,直到没有更多的节点可以被这种方式感染。

假设 M(initial) 是在恶意软件停止传播之后,整个网络中感染恶意软件的最终节点数。

我们可以从初始列表中删除一个节点。如果移除这一节点将最小化 M(initial), 则返回该节点。如果有多个节点满足条件,就返回索引最小的节点。

请注意,如果某个节点已从受感染节点的列表 initial 中删除,它以后可能仍然因恶意软件传播而受到感染。

示例 1:

输入:graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]
输出:0
示例 2:

输入:graph = [[1,0,0],[0,1,0],[0,0,1]], initial = [0,2]
输出:0
示例 3:

输入:graph = [[1,1,1],[1,1,1],[1,1,1]], initial = [1,2]
输出:1

思路:一个并查集的问题,通过并查集对数据进行处理,最后通过inital元素在并查集结果中的影响程度来判断选择哪个initial元素作为答案
1、对集合元素union,邻接矩阵
1的就进行关联
2、计算得出所有圈子
3、对inital的点进行遍历,计算这个点对应的圈子的大小(对应根节点的圈子大小)
4、如果圈子大小相同,返回值较小的
5、关键在于通过点计算圈子大小的方法,在每次union的时候,就计算出当前union对根节点的节点数大小的影响==

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: LeetCode 的第一题是 Two Sum。题目描述是:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。 解法: 1. 暴力枚举法:对于每一个数,遍历整个数组,找到另一个数使得它们的和为 target。时间复杂度为 O(n^2)。 2. Hash 表法:遍历数组,对于每一个数,用 target 减去该数,判断差值是否在数组中出现过,如果出现过就返回该数的下标和差值的下标。时间复杂度为 O(n)。 在 LeetCode 中,你可以使用任意一种方法来解决该题。 ### 回答2: leetcode第一题是要求找出数组中两个数的和等于给定目标数的索引。可以使用哈希表来解决这个问题。 首先,我们可以创建一个空的哈希表。然后,遍历整个数组,对于每一个元素,计算目标数减去当前元素的差值。接着,我们检查差值是否在哈希表中,如果存在,说明当前元素与差值的和等于目标数。我们可以直接返回当前元素和差值在哈希表中的索引。 如果差值不在哈希表中,我们将当前元素及其索引插入哈希表中,以便之后可以通过差值来找到当前元素的索引。遍历完成后,如果没有找到满足条件的索引,返回一个空数组或者其他指定的结果。 使用哈希表的解决方案可以将查找的时间复杂度降低到O(1)。整个算法的时间复杂度为O(n),其中n为数组的长度。算法的空间复杂度为O(n),因为需要额外的哈希表来存储元素及其索引。 总结起来,leetcode第一题可以通过使用哈希表来解决,其中遍历数组并将元素及其索引存储在哈希表中,然后查找差值是否在哈希表中,找到满足条件的索引并返回。这个解决方案的时间复杂度为O(n),空间复杂度为O(n)。 ### 回答3: LeetCode是一个在线的编程题库,第一题是非常简单的算法题。这个题目要求我们在一个整数数组中找到两个数,使得它们的和等于目标数。解决这个问题有几种方法。 一种简单的方法是使用双重循环来遍历数组中的每一对数,然后判断它们的和是否等于目标数。这样的时间复杂度是O(n^2),不是很高效。 另一种更优化的方法是使用哈希表。我们可以遍历一遍数组,将每个数与目标数的差值作为键,对应的索引作为值存放在哈希表中。然后再次遍历数组,每次都判断当前数在哈希表中是否存在,如果存在则说明找到了满足条件的两个数。这种方法的时间复杂度是O(n),空间复杂度也是O(n)。 还有一种更巧妙的方法是使用双指针。我们可以设置两个指针,一个指向数组的起始位置,一个指向数组的末尾位置,然后通过移动指针来逐渐缩小搜索范围。如果指针所指的两个数的和等于目标数,则找到了答案;如果和小于目标数,则将左指针右移一位;如果和大于目标数,则将右指针左移一位。这种方法的时间复杂度也是O(n),但空间复杂度是O(1),比哈希表方法更节省空间。 总之,这个题目虽然很简单,但是解决的方法有多种。根据题目要求和具体情况,我们可以选择适合的方法来解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值