【题解】—— LeetCode一周小结

1.经营摩天轮的最大利润

题目链接: 1599. 经营摩天轮的最大利润

你正在经营一座摩天轮,该摩天轮共有 4 个座舱 ,每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱,但每次轮转都需要支付一定的运行成本 runningCost 。摩天轮每次轮转都恰好转动 1 / 4 周。

给你一个长度为 n 的数组 customerscustomers[i] 是在第 i 次轮转(下标从 0 开始)之前到达的新游客的数量。这也意味着你必须在新游客到来前轮转 i 次。每位游客在登上离地面最近的座舱前都会支付登舱成本 boardingCost ,一旦该座舱再次抵达地面,他们就会离开座舱结束游玩。

你可以随时停下摩天轮,即便是 在服务所有游客之前 。如果你决定停止运营摩天轮,为了保证所有游客安全着陆,将免费进行所有后续轮转 。注意,如果有超过 4 位游客在等摩天轮,那么只有 4 位游客可以登上摩天轮,其余的需要等待 下一次轮转 。

返回最大化利润所需执行的 最小轮转次数 。 如果不存在利润为正的方案,则返回 -1

示例 1:
在这里插入图片描述

输入:customers = [8,3], boardingCost = 5, runningCost = 6
输出:3
解释:座舱上标注的数字是该座舱的当前游客数。

  1. 8 位游客抵达,4 位登舱,4 位等待下一舱,摩天轮轮转。当前利润为 4 * $5 - 1 * $6 = $14 。
  2. 3 位游客抵达,4 位在等待的游客登舱,其他 3 位等待,摩天轮轮转。当前利润为 8 * $5 - 2 * $6 = $28 。
  3. 最后 3 位游客登舱,摩天轮轮转。当前利润为 11 * $5 - 3 * $6 = $37 。 轮转 3 次得到最大利润,最大利润为 $37 。

示例 2:

输入:customers = [10,9,6], boardingCost = 6, runningCost = 4
输出:7
解释:

  1. 10 位游客抵达,4 位登舱,6 位等待下一舱,摩天轮轮转。当前利润为 4 * $6 - 1 * $4 = $20 。
  2. 9 位游客抵达,4 位登舱,11 位等待(2 位是先前就在等待的,9 位新加入等待的),摩天轮轮转。当前利润为 8 * $6 - 2 * $4 = $40 。
  3. 最后 6 位游客抵达,4 位登舱,13 位等待,摩天轮轮转。当前利润为 12 * $6 - 3 * $4 = $60 。
  4. 4 位登舱,9 位等待,摩天轮轮转。当前利润为 * $6 - 4 * $4 = $80 。
  5. 4 位登舱,5 位等待,摩天轮轮转。当前利润为 20 * $6 - 5 * $4 = $100 。
  6. 4 位登舱,1 位等待,摩天轮轮转。当前利润为 24 * $6 - 6 * $4 = $120 。
  7. 1 位登舱,摩天轮轮转。当前利润为 25 * $6 - 7 * $4 = $122 。 轮转 7 次得到最大利润,最大利润为$122 。

示例 3:

输入:customers = [3,4,0,5,1], boardingCost = 1, runningCost = 92
输出:-1
解释:

  1. 3 位游客抵达,3 位登舱,0 位等待,摩天轮轮转。当前利润为 3 * $1 - 1 * $92 = -$89 。
  2. 4 位游客抵达,4 位登舱,0 位等待,摩天轮轮转。当前利润为 7 * $1 - 2 * $92 = -$177 。
  3. 0 位游客抵达,0 位登舱,0 位等待,摩天轮轮转。当前利润为 7 * $1 - 3 * $92 = -$269 。
  4. 5 位游客抵达,4 位登舱,1 位等待,摩天轮轮转。当前利润为 11 * $1 - 4 * $92 = -$357 。
  5. 1 位游客抵达,2 位登舱,0 位等待,摩天轮轮转。当前利润为 13 * $1 - 5 * $92 = -$447 。 利润永不为正,所以返回 -1 。

提示:

n == customers.length

1 <= n <= 105

0 <= customers[i] <= 50

1 <= boardingCost, runningCost <= 100

题解

        新年第一天想到头痛

        看了半天题干里面 随时可以停下,免费进行后续 原来是指游客上摩天轮以后就不用管他们了…

方法1模拟

        我们可以直接模拟摩天轮的轮转过程,每次轮转时,累加等待的游客以及新到达的游客,然后最多 4 个人上船,更新等待的游客数和利润,记录最大利润与其对应的轮转次数。

class Solution {public int minOperationsMaxProfit(int[] customers, int boardingCost, int runningCost) {int ans = -1; // 初始化答案为-1,表示没有找到最大利润的方案int max = 0, t = 0; // 初始化最大利润为0,当前总利润为0int wait = 0, i = 0; // 初始化等待人数为0,轮转次数为0// 当等待人数大于0或者还有客户需要服务时,继续循环while (wait > 0 || i < customers.length) { // 如果还有游客,将等待人数加入等待游客的人数wait += i < customers.length ? customers[i] : 0; int up = Math.min(4, wait); // 计算可以上车的人数,最多为4人wait -= up; // 更新等待人数i++; // 轮转次数t += up * boardingCost - runningCost; // 更新当前总利润if (t > max) { // 如果当前总利润大于最大利润max = t; // 更新最大利润ans = i; // 更新答案为当前的轮转次数}}return ans; // 返回答案}
}

方法2贪心

        维护变量 time 代表转动的次数,那么成本就是 cost = time * runningCost;

        维护变量 customer 代表当前有多少等在上摩天轮的游客数量;

        枚举 customers[i] 那么当前 下标i 可以看做第几轮转动前的状态,那么更新 customer += customers[i] 得到当前等待的游客数量,由于存在大量游客(大于等于4)的可能,那么我们就可以直接得出,当前的等待游客如果 “尽量凑4人” 需要转多少轮,也就是更新 time += customer // 4 ,假设预计完成的轮次 time 大于当前 下标i 那么很明显,我们可以等后面游客过来补充 “填数”,如此形成循环。这个循环停止,代表当前游客不能再凑齐 4 人了,而且必须启动转一下,那么直接计算转一下把 “剩余游客” 接上。最后外循环判断还有没有下一轮游客过来即可;

        整个过程记录其最大利润并记录这个例如出现时的 time 即为答案;

        ps:计算如果直接用除法、乘法和余法会非常慢,可以直接位运算加速

class Solution {public int minOperationsMaxProfit(int[] customers, int boardingCost, int runningCost) {// 如果每次摩天轮的载客量乘以4小于等于运行成本,则无法盈利,返回-1if (boardingCost * 4 <= runningCost) return -1;int customer = 0, time = 0, income = 0, bestRes = 0, bestTime = -1;for (int i = 0; i < customers.length; ) {// 计算当前轮次前是否有新的游客加入,如果之前存在游客,尽量凑 4 人for (; i < customers.length && i <= time; i++) {customer += customers[i]; // 累加游客人数income += (customer >> 2 << 2) * boardingCost; // 计算收入time += customer >> 2; // 更新轮转次数customer &= 3; // 更新剩余游客人数}// 上轮循环跳出证明当前出现无游客凑够 4 人的情况,所以先核算之前满载 4 人的最优情况下利润是否创新高if (bestRes < income - runningCost * time) {bestRes = income - runningCost * time; // 更新最佳利润bestTime = time; // 更新轮转次数}// 到这里证明游客少于 4 人,且必须转动,那么就直接计算并判断income += boardingCost * customer; // 计算收入customer = 0; // 更新剩余游客人数time++; // 更新轮转次数if (bestRes < income - runningCost * time) {bestRes = income - runningCost * time; // 更新最佳利润bestTime = time; // 更新轮转次数}}return bestTime; // 返回轮转次数}
}

2.统计重复个数

题目链接:466. 统计重复个数

定义 str = [s, n] 表示 strn 个字符串 s 连接构成。

  • 例如,str == ["abc", 3] =="abcabcabc"

如果可以从 s2 中删除某些字符使其变为 s1,则称字符串 s1 可以从字符串 s2 获得。

  • 例如,根据定义,s1 = "abc" 可以从 s2 = "abdbec" 获得,仅需要删除加粗且用斜体标识的字符。

现在给你两个字符串 s1s2 和两个整数 n1n2 。由此构造得到两个字符串,其中 str1 = [s1, n1]str2 = [s2, n2]

请你找出一个最大整数 m ,以满足 str = [str2, m] 可以从 str1 获得。

示例 1:

输入:s1 = “acb”, n1 = 4, s2 = “ab”, n2 = 2
输出:2

示例 2:

输入:s1 = “acb”, n1 = 1, s2 = “acb”, n2 = 1
输出:1

提示:

1 <= s1.length, s2.length <= 100

s1 和 s2 由小写英文字母组成

1 <= n1, n2 <= 106

题解

方法(来自官方题解):找出循环节(个人觉得太麻烦)
思路

        由于题目中的 n1 和 n2 都很大,因此我们无法真正把 S1 = [s1, n1] 和 S2 = [s2, n2] 都显式地表示出来。由于这两个字符串都是不断循环的,因此我们可以考虑找出 S2 在 S1 中出现的循环节,如果我们找到了循环节,那么我们就可以很快算出 S2 在 S1 中出现了多少次了。

        有些读者可能对循环节这个概念会有些陌生,这个概念我们可以类比无限循环小数,如果从小数部分的某一位起向右进行到某一位止的一节数字「循环」出现,首尾衔接,称这种小数为「无限循环小数」,这一节数字称为「无限循环小数」。比如对于 3.56789789789… 这个无限循环小数,它的小数部分就是以 789 为一个「循环节」在无限循环,且开头可能会有部分不循环的部分,这个数字中即为 56。

        那么回到这题,我们可以将不断循环的 s2 组成的字符串类比作上面小数部分,去找是否存在一个子串,即「循环节」,满足不断在 S2 中循环,且这个循环节能对应固定数量的 s1 。如下图所示,在第一次出现后,S2 的子串 bdadc 构成一个循环节:之后 bdadc 的每次出现都需要有相应的两段 s1。
在这里插入图片描述
        当我们找出循环节后,我们即可知道一个循环节内包含 s1 的数量,以及在循环节出现前的 s1 的数量,这样就可以在 O(1)的时间内,通过简单的运算求出 s2 在 S1 中出现的次数了。当然,由于 S1 中 s1 的数量 n1 是有限的,因此可能会存在循环节最后一个部分没有完全匹配,如上图最后会单独剩一个 s1 出来无法完全匹配完循环节,这部分我们需要单独拿出来遍历处理统计。

        有些读者可能会怀疑循环节是否一定存在,这里我们给出的答案是肯定的,根据鸽笼原理,我们最多只要找过 |s2| + 1 个 s1,就一定会出现循环节。

class Solution {public int getMaxRepetitions(String s1, int n1, String s2, int n2) {if (n1 == 0) {return 0;}int s1cnt = 0, index = 0, s2cnt = 0;// recall 是我们用来找循环节的变量,它是一个哈希映射// 我们如何找循环节?假设我们遍历了 s1cnt 个 s1,此时匹配到了第 s2cnt 个 s2 中的第 index 个字符// 如果我们之前遍历了 s1cnt' 个 s1 时,匹配到的是第 s2cnt' 个 s2 中同样的第 index 个字符,那么就有循环节了// 我们用 (s1cnt', s2cnt', index) 和 (s1cnt, s2cnt, index) 表示两次包含相同 index 的匹配结果// 那么哈希映射中的键就是 index,值就是 (s1cnt', s2cnt') 这个二元组// 循环节就是;//    - 前 s1cnt' 个 s1 包含了 s2cnt' 个 s2//    - 以后的每 (s1cnt - s1cnt') 个 s1 包含了 (s2cnt - s2cnt') 个 s2// 那么还会剩下 (n1 - s1cnt') % (s1cnt - s1cnt') 个 s1, 我们对这些与 s2 进行暴力匹配// 注意 s2 要从第 index 个字符开始匹配Map<Integer, int[]> recall = new HashMap<Integer, int[]>();int[] preLoop = new int[2];int[] inLoop = new int[2];while (true) {// 我们多遍历一个 s1,看看能不能找到循环节++s1cnt;for (int i = 0; i < s1.length(); ++i) {char ch = s1.charAt(i);if (ch == s2.charAt(index)) {index += 1;if (index == s2.length()) {++s2cnt;index = 0;}}}// 还没有找到循环节,所有的 s1 就用完了if (s1cnt == n1) {return s2cnt / n2;}// 出现了之前的 index,表示找到了循环节if (recall.containsKey(index)) {int[] value = recall.get(index);int s1cntPrime = value[0];int s2cntPrime = value[1];// 前 s1cnt' 个 s1 包含了 s2cnt' 个 s2preLoop = new int[]{s1cntPrime, s2cntPrime};// 以后的每 (s1cnt - s1cnt') 个 s1 包含了 (s2cnt - s2cnt') 个 s2inLoop = new int[]{s1cnt - s1cntPrime, s2cnt - s2cntPrime};break;} else {recall.put(index, new int[]{s1cnt, s2cnt});}}// ans 存储的是 S1 包含的 s2 的数量,考虑的之前的 preLoop 和 inLoopint ans = preLoop[1] + (n1 - preLoop[0]) / inLoop[0] * inLoop[1];// S1 的末尾还剩下一些 s1,我们暴力进行匹配int rest = (n1 - preLoop[0]) % inLoop[0];for (int i = 0; i < rest; ++i) {for (int j = 0; j < s1.length(); ++j) {char ch = s1.charAt(j);if (ch == s2.charAt(index)) {++index;if (index == s2.length()) {++ans;index = 0;}}}}// S1 包含 ans 个 s2,那么就包含 ans / n2 个 S2return ans / n2;}
}

方法:递归
        我们预处理出以字符串 s2 的每个位置 i 开始匹配一个完整的 s1 后,下一个位置 jjj 以及经过了多少个 s2,即 d[i]=(cnt,j),其中 cnt 表示匹配了多少个 s2,而 j 表示字符串 s2 的下一个位置。

        接下来,我们初始化 j=0,然后循环 n1 次,每一次将 d[j][0] 加到答案中,然后更新 j=d[j][1]。

        最后得到的答案就是 n1 个 s1所能匹配的 s2 的个数,除以 n2 即可得到答案。

class Solution {public int getMaxRepetitions(String s1, int n1, String s2, int n2) {int len1 = s1.length();int len2 = s2.length();int[][] DP = new int[len2][0]; // 0 记录s2匹配的个数 1 记录下一个s2匹配的位置for (int i = 0; i < len2; i++) {int j = i; // 记录下一个s2匹配的位置int cnt = 0; // 记录s2匹配的个数: 一个s1中可能含有多个s2串for (int k = 0; k < len1; k++) { // 遍历s1字符串进行匹配if (s1.charAt(k) == s2.charAt(j)) { // 匹配相同的字符串j++; // 指向下一个位置if (j == len2) { // s2匹配完一段j = 0; // 重置索引cnt++; // 匹配个数加1}}}// 循环结束,j的位置始终对标在s1中的位置DP[i] = new int[]{cnt, j}; // 匹配完一次 则将结果添加到数组中}int ans = 0; // 定义结果变量for (int j = 0; n1 > 0; n1--) { // 遍历n1,记录每个循环中s2下标出现的数量ans += DP[j][0]; // 累加匹配数j = DP[j][1]; // 获取下一个位置}return ans / n2; // 将n2个s2作为一个整体数量,砍掉n2个就是结果}
}

3.从链表中移除节点

题目链接:2487. 从链表中移除节点

给你一个链表的头节点 head 。

移除每个右侧有一个更大数值的节点。

返回修改后链表的头节点 head 。

示例 1:
在这里插入图片描述

输入:head = [5,2,13,3,8]
输出:[13,8]
解释:需要移除的节点是 5 ,2 和 3 。

  • 节点 13 在节点 5 右侧。
  • 节点 13 在节点 2 右侧。
  • 节点 8 在节点 3 右侧。

示例 2:

输入:head = [1,1,1,1]
输出:[1,1,1,1]
解释:每个节点的值都是 1 ,所以没有需要移除的节点。

提示:

给定列表中的节点数目在范围 [1, 105] 内
1 <= Node.val <= 105

题解

方法:递归
        由题意可知,节点对它右侧的所有节点都没有影响,因此我们可以对它的右侧节点递归地进行移除操作:

  • 该节点为空,那么递归函数返回空指针。

  • 该节点不为空,那么先对它的右侧节点进行移除操作,得到一个新的子链表,如果子链表的表头节点值大于该节点的值,那么移除该节点,否则将该节点作为子链表的表头节点,最后返回该子链表。

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode removeNodes(ListNode head) {if (head == null) {return null;}head.next = removeNodes(head.next);if (head.next != null && head.val < head.next.val) {return head.next;} else {return head;}}
}

4.被列覆盖的最多行数

题目链接:2397. 被列覆盖的最多行数

给你一个下标从 0 开始、大小为 m x n 的二进制矩阵 matrix ;另给你一个整数 numSelect,表示你必须从 matrix 中选择的 不同 列的数量。

如果一行中所有的 1 都被你选中的列所覆盖,则认为这一行被 覆盖 了。

形式上,假设 s = {c1, c2, ...., cnumSelect} 是你选择的列的集合。对于矩阵中的某一行 row ,如果满足下述条件,则认为这一行被集合 s 覆盖:

  • 对于满足 matrix[row][col] == 1 的每个单元格 matrix[row][col]0 <= col <= n - 1),col 均存在于 s 中,或者
  • row不存在 值为 1 的单元格。
    你需要从矩阵中选出 numSelect 个列,使集合覆盖的行数最大化。

返回一个整数,表示可以由 numSelect 列构成的集合 覆盖最大行数

示例 1:
在这里插入图片描述

输入:matrix = [[0,0,0],[1,0,1],[0,1,1],[0,0,1]], numSelect = 2
输出:3
解释:
图示中显示了一种覆盖 3 行的可行办法。 选择 s = {0, 2} 。

  • 第 0 行被覆盖,因为其中没有出现 1 。
  • 第 1 行被覆盖,因为值为 1 的两列(即 0 和 2)均存在于 s 中。
  • 第 2 行未被覆盖,因为 matrix[2][1] == 1 但是 1 未存在于 s 中。
  • 第 3 行被覆盖,因为 matrix[2][2] == 1 且 2 存在于 s 中。 因此,可以覆盖 3 行。 另外 s = {1, 2} 也可以覆盖 3 行,但可以证明无法覆盖更多行。

示例 2:
在这里插入图片描述

输入:matrix = [[1],[0]], numSelect = 1
输出:2
解释:
选择唯一的一列,两行都被覆盖了,因为整个矩阵都被覆盖了。 所以我们返回 2 。

提示:

m == matrix.length
n == matrix[i].length
1 <= m, n <= 12
matrix[i][j]要么是 0 要么是 1
1 <= numSelect <= n

题解
方法:二进制枚举

        我们先将矩阵中的每一行转换成一个二进制数,记录在数组 rows中,其中 rows[i]表示第 i 行对应的二进制数,而 rows[i] 这个二进制数的第 j 位表示矩阵第 i 行第 j 列的值。

        接下来,我们枚举所有的 2n2 种列选择方案,其中 n 为矩阵的列数。对于每一种列选择方案,我们判断是否选中了 numSelect列,如果不是,则跳过。否则,我们统计矩阵中有多少行中的所有 1 都被选中的列覆盖,即统计有多少行的二进制数 rows[i]与列选择方案 mask 按位与的结果等于 rows[i],并更新最大的行数。

class Solution {public int maximumRows(int[][] matrix, int numSelect) {// 获取矩阵的行数m和列数nint m = matrix.length, n = matrix[0].length;// 定义一个长度为m的一维数组rows,用于存储每一行的二进制表示int[] rows = new int[m];// 遍历矩阵的每一行for (int i = 0; i < m; ++i) {// 遍历矩阵的每一列for (int j = 0; j < n; ++j) {// 如果当前位置的元素值为1,则将该位置对应的二进制位设置为1if (matrix[i][j] == 1) {rows[i] |= 1 << j;}}}// 初始化答案ans为0int ans = 0;// 遍历所有可能的二进制掩码(从1到2^n-1)for (int mask = 1; mask < 1 << n; ++mask) {// 如果当前掩码中1的个数不等于numSelect,则跳过当前循环if (Integer.bitCount(mask) != numSelect) {continue;}// 初始化计数器t为0int t = 0;// 遍历每一行的二进制表示for (int x : rows) {// 如果当前行的二进制表示与当前掩码进行按位与运算后的结果等于当前行的二进制表示,则计数器t加1if ((x & mask) == x) {++t;}}// 更新答案ans为ans和t中的较大值ans = Math.max(ans, t);}// 返回答案ansreturn ans;}
}

5.队列中可以看到的人数

题目链接:1944. 队列中可以看到的人数

有 n 个人排成一个队列,从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights ,每个整数 互不相同,heights[i] 表示第 i 个人的高度。

一个人能 看到 他右边另一个人的条件是这两人之间的所有人都比他们两人 。更正式的,第 i 个人能看到第 j 个人的条件是 i < j 且 min(heights[i], heights[j]) > max(heights[i+1], heights[i+2], …, heights[j-1]) 。

请你返回一个长度为 n 的数组 answer ,其中 answer[i] 是第 i 个人在他右侧队列中能 看到人数

示例 1:在这里插入图片描述

输入:heights = [10,6,8,5,11,9]
输出:[3,1,2,1,1,0]
解释:
第 0 个人能看到编号为 1 ,2 和
4 的人。
第 1 个人能看到编号为 2 的人。
第 2 个人能看到编号为 3 和 4 的人。
第 3 个人能看到编号为 4 的人。
第 4个人能看到编号为 5 的人。
第 5 个人谁也看不到因为他右边没人。

示例 2:

输入:heights = [5,1,2,3,10]
输出:[4,1,1,1,0]

提示:

n == heights.length

1 <= n <= 105

1 <= heights[i] <= 105

heights 中所有数 互不相同 。

提示 1

如何在二次复杂度中解决这个问题?

提示 2

对于从索引i开始的每个子数组,继续寻找新的最大值,直到找到一个大于arr[i]的值。

提示 3

因为极限很高,你需要一个线性解。

提示 4

在从末尾到开始迭代数组时,使用堆栈来保持数组值的排序。

提示 5

继续从堆栈中弹出元素,直到找到一个大于arr[i]的值,这些是我可以看到的人。

题解
方法:单调栈
        由题可知,对于第 i 个人来说,他能看到的人一定是按从左到右高度严格单调递增的。

        因此,我们可以倒序遍历数组 heights,用一个从栈顶到栈底单调递增的栈 stk 记录已经遍历过的人的高度。

        对于第 i 个人,如果栈不为空并且栈顶元素小于 heights[i],累加当前第 i 个人能看到的人数,然后将栈顶元素出栈,直到栈为空或者栈顶元素大于等于 heights[i]。如果此时栈不为空,说明栈顶元素大于等于 heights[i],那么第 i 个人能看到的人数还要再加 1。

        接下来,我们将 heights[i]入栈,继续遍历下一个人。

        遍历结束后,返回答案数组 ans。

class Solution {public int[] canSeePersonsCount(int[] heights) { int n = heights.length; int[] ans = new int[n]; Deque<Integer> stk = new ArrayDeque<>(); // 双端队列stk,用于存储高度信息for (int i = n - 1; i >= 0; --i) { // 倒序遍历数组while (!stk.isEmpty() && stk.peek() < heights[i]) { // 如果栈不为空且栈顶元素小于当前元素stk.pop(); // 弹出栈顶元素++ans[i]; }if (!stk.isEmpty()) { ++ans[i];}stk.push(heights[i]); // 将当前元素压入栈中}return ans; }
}

6.在链表中插入最大公约数

题目链接: 2807. 在链表中插入最大公约数

给你一个链表的头 head ,每个结点包含一个整数值。

在相邻结点之间,请你插入一个新的结点,结点值为这两个相邻结点值的 最大公约数

请你返回插入之后的链表。

两个数的 最大公约数 是可以被两个数字整除的最大正整数。

示例 1:
在这里插入图片描述

输入:head = [18,6,10,3]

输出:[18,6,6,2,10,1,3]

解释:第一幅图是一开始的链表,第二幅图是插入新结点后的图(蓝色结点为新插入结点)。

  • 18 和 6 的最大公约数为 6 ,插入第一和第二个结点之间。
  • 6 和 10 的最大公约数为 2 ,插入第二和第三个结点之间。
  • 10 和 3 的最大公约数为 1 ,插入第三和第四个结点之间。

所有相邻结点之间都插入完毕,返回链表。

示例 2:

在这里插入图片描述

输入:head = [7]

输出:[7]

解释:第一幅图是一开始的链表,第二幅图是插入新结点后的图(蓝色结点为新插入结点)。

没有相邻结点,所以返回初始链表。

提示:

链表中结点数目在 [1, 5000] 之间。

1 <= Node.val <= 1000

题解
方法:遍历
        遍历链表,在当前节点node 后面插入gcd节点,同时gcd节点指向下一个node 节点。

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {// 插入最大公约数节点的方法public ListNode insertGreatestCommonDivisors(ListNode head) {ListNode node = head; // 初始化当前节点为头节点while (node.next != null) { // 遍历链表,直到最后一个节点node.next = new ListNode(gcd(node.val, node.next.val), node.next); // 将当前节点的下一个节点替换为最大公约数节点node = node.next.next; // 移动到新插入的最大公约数节点的下一个节点}return head; // 返回修改后的链表头节点}// 计算两个整数的最大公约数的方法public int gcd(int a, int b) {while (b != 0) { // 当b不为0时,继续循环int tmp = a % b; // 计算a除以b的余数a = b; // 将b的值赋给ab = tmp; // 将余数赋给b}return a; // 返回最大公约数}
}

7.赎金信

题目链接:383. 赎金信

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

示例 1:

输入:ransomNote = “a”, magazine = “b”

输出:false

示例 2:

输入:ransomNote = “aa”, magazine = “ab”

输出:false

示例 3:

输入:ransomNote = “aa”, magazine = “aab”

输出:true

提示:

1 <= ransomNote.length, magazine.length <= 105

ransomNote 和 magazine 由小写英文字母组成

题解

class Solution {public boolean canConstruct(String ransomNote, String magazine) {int[] memo = new int[26];// 遍历magazine字符串中的每个字符,将其转换为小写字母后在memo数组中对应的位置加1for (char ch : magazine.toCharArray()) memo[ch - 'a']++;// 遍历ransomNote字符串中的每个字符,将其转换为小写字母后在memo数组中对应的位置减1for (char ch : ransomNote.toCharArray()) if (--memo[ch - 'a'] < 0) return false;// 如果减1后的值小于0,说明ransomNote中的某个字符在magazine中不存在,返回false// 如果ransomNote中的所有字符都在magazine中存在,返回truereturn true;}
}

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

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

相关文章

Docker简介、基本概念和安装

Docker简介、基本概念和安装 1.docker简介 1.1 什么是docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes (opens new window)在法国期间发起的一个公司内部项目&#xff0c;它是基于 dotCloud 公司多年云服务技术的一次革新&#xff0c;并于 2013 年 3 月以 Apache 2…

Objective-C中使用STL标准库Queue队列

1.修改.m文件为mm 2.导入queue头 #include<queue> 3.使用&#xff1a; #import <Foundation/Foundation.h> #include <cmath> #include <queue> using namespace std;int main(int argc, const char * argv[]) {autoreleasepool {NSLog("C标准…

云计算任务调度仿真01

云计算任务调度的研究大多数以来仿真研究&#xff0c;现梳理一些做过的代码研究 结果无数次的排错&#xff0c;终于finish with code 0 了 这个代码以来的是比较老的TensorFlow版本&#xff0c;我们都知道TensorFlow1.x和TensorFlow2.x之间有很大差别&#xff0c;但其实&#…

Realm Management Extension领域管理扩展之安全状态

RME基于Arm TrustZone技术。TrustZone技术在Armv6中引入,提供以下两个安全状态: 安全状态(Secure state)非安全状态(Non-secure state)以下图表显示了在AArch64中的这两个安全状态以及通常在每个安全状态中找到的软件组件: 该架构将在安全状态运行的软件与在非安全状态运…

openGauss学习笔记-190 openGauss 数据库运维-常见故障定位案例-服务启动失败

文章目录 openGauss学习笔记-190 openGauss 数据库运维-常见故障定位案例-服务启动失败190.1 服务启动失败190.1.1 问题现象190.1.2 原因分析190.1.3 处理办法 openGauss学习笔记-190 openGauss 数据库运维-常见故障定位案例-服务启动失败 190.1 服务启动失败 190.1.1 问题现…

Copilot 插件的使用介绍:如何快速上手

GitHub Copilot 本文主要介绍如何通过脚本工具激活 GitHub Copilot 插件&#xff0c;提供安装及激活图文教程&#xff0c;大家按下面操作即可激活GitHub Copilot插件&#xff0c;免费使用Ai编码工具 一、GitHub Copilot 介绍 GitHub Copilot 是由 GitHub 和 OpenAI 共同开发的…

告别冗余空白,批量删除空白行

你是否遇到过这样的尴尬情况&#xff1a;花费了大量时间整理的文档&#xff0c;却在最后发现其中充斥着无用的空白行&#xff0c;这些多余的空行不仅影响美观&#xff0c;还让整个文档显得杂乱无章。今天&#xff0c;我要给大家介绍一款强大且实用的工具——首助编辑高手&#…

移动端对大批量图片加载的优化方法(三)

移动端对大批量图片加载的优化方法&#xff08;三&#xff09;Flutter 本篇主要从Flutter开发中可以使用到的对大批量图片加载的优化方法进行整理。 1.合适的图片格式 详情请参考移动端对大批量图片加载的优化方法&#xff08;一&#xff09;。 2.缓存机制 在Flutter中&am…

浅谈对Promise的理解。

一、Promise定义 JS中用于处理异步操作的编程模式。一个Promise是一个代理&#xff0c;它代表一个创建Promise时不一定已知的值。它允许我们将处理的程序与异步操作的最终成功值或失败值原因想关联起来。这使得异步方法可以像同步方法一样返回值&#xff1a;异步方法不会立即返…

uniapp最简单的底部兼容安全区域显示

效果图&#xff1a; 1.html写上动态padding-bottom <view class"button-wrap" :style"padding-bottom:bottomPaddingrpx"><view class"com-btn cencel-btn">取消</view><view class"com-btn confirm-btn " cl…

【PostgreSQL创建索引的锁分析和使用注意】

1.1 创建普通B-tree索引的整体流程 如下是梳理的创建普通B-tree索引的大概流程&#xff0c;可供参考。 1.校验新索引的Catalog元数据|语法解析 ---将创建索引的sql解析成IndexStmt结构&#xff5c;校验B-Tree的handler -----校验内核是否支持该类型的索引,在pg_am中查找&q…

java 体育明星管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web 体育明星管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysq…

Clojure 实战(4):编写 Hadoop MapReduce 脚本

Hadoop简介 众所周知&#xff0c;我们已经进入了大数据时代&#xff0c;每天都有PB级的数据需要处理、分析&#xff0c;从中提取出有用的信息。Hadoop就是这一时代背景下的产物。它是Apache基金会下的开源项目&#xff0c;受Google两篇论文的启发&#xff0c;采用分布式的文件…

Spark Core--加强

RDD的持久化 RDD缓存 当RDD被重复使用&#xff0c;或者计算该RDD比较容易出错&#xff0c;而且需要消耗比较多的资源和时间的时候&#xff0c;我们就可以将该RDD缓存起来。 主要作用: 提升Spark程序的计算效率 注意事项: RDD的缓存可以存储在内存或者是磁盘上&#xff0c;甚至…

【数据结构】二叉树链式结构详解

目录 1.前言2.快速创建一颗二叉树3.二叉树的遍历3.1前序遍历3.2中序遍历3.3后序遍历3.4层序遍历 4.二叉树节点个数与高度4.1二叉树节点个数4.2二叉树叶子节点个数4.3二叉树高度4.4二叉树第k层节点个数4.5二叉树查找值为x的节点 5.二叉树的基础oj题练习6.二叉树的创建和销毁6.1通…

JVM,JRE,JDK的区别和联系简洁版

先看图 利用JDK&#xff08;调用JAVA API&#xff09;开发JAVA程序后&#xff0c;通过JDK中的编译程序&#xff08;javac&#xff09;将我们的文本java文件编译成JAVA字节码&#xff0c;在JRE上运行这些JAVA字节码&#xff0c;JVM解析这些字节码&#xff0c;映射到CPU指令集或…

Spring学习 基于注解的AOP配置

5.1.创建工程 5.1.1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.ap…

springCould中的Config-从小白开始【10 】

目录 &#x1f32d;1.spring cloud Config是什么&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️ &#x1f953;2.能干什么&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️ &am…

SSH远程访问出现Permission denied(password)解决方法

首先&#xff0c;这个不是密码输错了的问题&#xff1b; 1、在主机先ping一下服务器 ping XXX.XXX.XX.XXX (服务器ip地址) 如果pin成功了&#xff0c;说明可以进行连接 查看服务器的ip ifconfig2、主机连接服务器 &#xff08;服务器的ip&#xff09; ssh testXXX.XXX.XX.…

LeetCode-数组-双指针-中等难度

文章目录 双指针1. 删除有序数组中的重复项&#xff08;入门&#xff09;1.1 题目描述1.2 解题思路1.3 代码实现 2. 删除有序数组中的重复项 II&#xff08;简单&#xff09;2.1 题目描述2.2 解题思路2.3 代码实现 3. 移动零&#xff08;简单&#xff09;3.1 题目描述3.2 代码实…