LeetCode算法:400~899道

目录
400. 第 N 个数字
401. 二进制手表
402. 移掉 K 位数字
404. 左叶子之和
405. 数字转换为十六进制数
406. 根据身高重建队列
409. 最长回文串
410. 分割数组的最大值
414. 第三大的数
415. 字符串相加
421. 数组中两个数的最大异或值
424. 替换后的最长重复字符
426. 将二叉搜索树转化为排序的双向链表
430. 扁平化多级双向链表
437. 路径总和 III
441. 排列硬币
442. 数组中重复的数据
445. 两数相加 II
448. 找到所有数组中消失的数字
449. 序列化和反序列化二叉搜索树
450. 删除二叉搜索树中的节点
452. 用最少数量的箭引爆气球
453. 最小移动次数使数组元素相等
454. 四数相加 II
456. 132 模式
458. 可怜的小猪
459. 重复的子字符串
461. 汉明距离
462. 最少移动次数使数组元素相等 II
473. 火柴拼正方形
475. 供暖器
477. 汉明距离总和
483. 最小好进制
485. 最大连续 1 的个数
486. 预测赢家
487. 最大连续 1 的个数 II
490. 迷宫
492. 构造矩形
494. 目标和
496. 下一个更大元素 I
500. 键盘行
501. 二叉搜索树中的众数
502. IPO
503. 下一个更大元素 II
504. 七进制数
506. 相对名次
507. 完美数
508. 出现次数最多的子树元素和
509. 斐波那契数
513. 找树左下角的值
515. 在每个树行中找最大值
518. 零钱兑换 II
520. 检测大写字母
521. 最长特殊序列 Ⅰ
522. 最长特殊序列 II
523. 连续的子数组和
525. 连续数组
526. 优美的排列
530. 二叉搜索树的最小绝对差
538. 把二叉搜索树转换为累加树
541. 反转字符串 II
542. 01 矩阵
543. 二叉树的直径
554. 砖墙
556. 下一个更大元素 III
557. 反转字符串中的单词 III
560. 和为 K 的子数组
561. 数组拆分 I
563. 二叉树的坡度
566. 重塑矩阵
572. 另一个树的子树
576. 出界的路径数
581. 最短无序连续子数组
589. N 叉树的前序遍历
590. N 叉树的后序遍历
605. 种花问题
606. 根据二叉树创建字符串
611. 有效三角形的个数
617. 合并二叉树
622. 设计循环队列
633. 平方数之和
637. 二叉树的层平均值
645. 错误的集合
650. 只有两个键的键盘
652. 寻找重复的子树
664. 奇怪的打印机
669. 修剪二叉搜索树
671. 二叉树中第二小的节点
673. 最长递增子序列的个数
674. 最长连续递增序列
679. 24 点游戏
682. 棒球比赛
684. 冗余连接
687. 最长同值路径
690. 员工的重要性
695. 岛屿的最大面积
696. 计数二进制子串
697. 数组的度
700. 二叉搜索树中的搜索
701. 二叉搜索树中的插入操作
703. 数据流中的第 K 大元素
704. 二分查找
707. 设计链表
718. 最长重复子数组
724. 寻找数组的中心索引
725. 分隔链表
739. 每日温度
740. 删除与获得点数
746. 使用最小花费爬楼梯
752. 打开转盘锁
760. 找出变位映射
766. 托普利茨矩阵
771. 宝石与石头
777. 在 LR 字符串中交换相邻字符
783. 二叉搜索树结点最小距离
784. 字母大小写全排列
814. 二叉树剪枝
817. 链表组件
829. 连续整数求和
832. 翻转图像
852. 山脉数组的峰顶索引
856. 括号的分数
857. 雇佣 K 名工人的最低成本
860. 柠檬水找零
862. 和至少为 K 的最短子数组
872. 叶子相似的树
875. 爱吃香蕉的珂珂
876. 链表的中间结点
878. 第 N 个神奇数字
883. 三维形体投影面积
887. 鸡蛋掉落
891. 子序列宽度之和
892. 三维形体的表面积
897. 递增顺序查找树
898. 子数组按位或操作

400. 第 N 个数字

English Version

题目描述

在无限的整数序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...中找到第 个数字。

注意:
是正数且在32为整形范围内 ( n < 231)。

示例 1:

输入:
3

输出:
3

示例 2:

输入:
11

输出:
0

说明:
第11个数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是0,它是10的一部分。

解法

Python3


Java

class Solution {
    /***
     * 12345678910111213
     * 规律个位数9个数一共有9*1,两位数90个数 一共有90*2个数字,三位数有900个数一共有900*3个数字,以此类推
     * 举例15,15-9=6,6/2=3...0,余数是0,那么这个数值value=10*(2-1)+(3-1)=12,整除取最后一位  12%10=2
     * 举例14,14-9=5,5/2=2...1,余数不为0,那么这个数值value=10*(2-1)+2=12,则为这个数的第余数个 12/(10*(2-1))%10=1
     */
    public int findNthDigit(int n) {
        long max = 9;
        long num = n;
        long digits = 1;
        while (n > 0) {
            if (num - max * digits > 0) {
                num = num - max * digits;
                digits++;
                max = max * 10;
            } else {
                long count = num / digits;
                long childDigits = num % digits;
                if (childDigits == 0) {
                    return (int) (((long) Math.pow(10, digits - 1) + count - 1) % 10);
                } else {
                    return (int) (((long) Math.pow(10, digits - 1) + count) / ((long) Math.pow(10, (digits - childDigits))) % 10);
                }
            }
        }
        return 0;
    }
}


401. 二进制手表

English Version

题目描述

二进制手表顶部有 4 个 LED 代表小时(0-11),底部的 6 个 LED 代表分钟(0-59)

每个 LED 代表一个 0 或 1,最低位在右侧。

例如,上面的二进制手表读取 “3:25”。

给定一个非负整数 代表当前 LED 亮着的数量,返回所有可能的时间。

案例:

输入: n = 1
返回: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]

 

注意事项:

  • 输出的顺序没有要求。
  • 小时不会以零开头,比如 “01:00” 是不允许的,应为 “1:00”。
  • 分钟必须由两位数组成,可能会以零开头,比如 “10:2” 是无效的,应为 “10:02”。

解法

Python3


Java

class Solution {
    public List<String> readBinaryWatch(int num) {
        List<String> res = new ArrayList<>();
        for (int i = 0; i < 12; ++i) {
            for (int j = 0; j < 60; ++j) {
                if (Integer.bitCount(i) + Integer.bitCount(j) == num) {
                    res.add(String.format("%d:%02d", i, j));
                }
            }
        }
        return res;
    }
}


402. 移掉 K 位数字

English Version

题目描述

给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

注意:

  • num 的长度小于 10002 且 ≥ k。
  • num 不会包含任何前导零。

示例 1 :

输入: num = "1432219", k = 3
输出: "1219"
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。

示例 2 :

输入: num = "10200", k = 1
输出: "200"
解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。

示例 3 :

输入: num = "10", k = 2
输出: "0"
解释: 从原数字移除所有的数字,剩余为空就是0。

解法

Python3


Java

class Solution {
    public String removeKdigits(String num, int k) {
        if (k <= 0) {
            return num;
        }
        if (num.length() <= k) {
            return "0";
        }
        int len = num.length() - k;
        char[] cs = new char[num.length()];
        int top = -1;
        for (char c : num.toCharArray()) {
            while (top >= 0 && cs[top] > c && k > 0) {
                --top;
                --k;
            }
            cs[++top] = c;
        }
        int offset = 0;
        while (offset <= top && cs[offset] == '0') {
            ++offset;
        }
        return offset > top ? "0" : new String(cs, offset, len - offset);
    }
}


404. 左叶子之和

English Version

题目描述

计算给定二叉树的所有左叶子之和。

示例:

    3
   / \
  9  20
    /  \
   15   7

在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

 

解法

Python3


Java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    private int sum = 0;

    public int sumOfLeftLeaves(TreeNode root) {
        if (root == null) return 0;
        if (root.left != null && root.left.left == null && root.left.right == null) {
            sum += root.left.val;
        }
        sumOfLeftLeaves(root.left);
        sumOfLeftLeaves(root.right);
        return sum;
    }
}


405. 数字转换为十六进制数

English Version

题目描述

给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。

注意:

  1. 十六进制中所有字母(a-f)都必须是小写。
  2. 十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符'0'来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。 
  3. 给定的数确保在32位有符号整数范围内。
  4. 不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。

示例 1:

输入:
26

输出:
"1a"

示例 2:

输入:
-1

输出:
"ffffffff"

解法

Python3


Java

class Solution {
    public String toHex(int num) {
        if (num == 0) {
            return "0";
        }
        StringBuilder sb = new StringBuilder();
        while (num != 0) {
            int x = num & 15;
            if (x < 10) {
                sb.append(x);
            } else {
                sb.append((char) (x - 10 + 'a'));
            }
            num >>>= 4;
        }
        return sb.reverse().toString();
    }
}


406. 根据身高重建队列

English Version

题目描述

假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。

注意:
总人数少于1100人。

示例

输入:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

输出:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]

解法

Python3


Java

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        Arrays.sort(people, (o1, o2) -> o1[0] != o2[0] ? Integer.compare(o2[0], o1[0]) : Integer.compare(o1[1], o2[1]));
        List<int[]> res = new ArrayList<>(people.length);
        for (int[] p : people) {
            res.add(p[1], p);
        }
        return res.toArray(new int[res.size()][]);
    }
}


409. 最长回文串

English Version

题目描述

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。

在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。

注意:
假设字符串的长度不会超过 1010。

示例 1:

输入:
"abccccdd"

输出:
7

解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。

解法

Python3

class Solution:
    def longestPalindrome(self, s: str) -> int:
        res = [0] * 128
        for ch in s:
            res[ord(ch)] += 1
        odd_cnt, n = 0, len(s)
        for e in res:
            odd_cnt += (e % 2)
        return n if odd_cnt == 0 else n - odd_cnt + 1

Java

class Solution {
    public int longestPalindrome(String s) {
        int[] res = new int[128];
        int n = s.length();
        for (int i = 0; i < n; ++i) {
            res[s.charAt(i)]++;
        }
        int oddCnt = 0;
        for (int e : res) {
            oddCnt += (e % 2);
        }
        return oddCnt == 0 ? n : n - oddCnt + 1;
    }
}


410. 分割数组的最大值

English Version

题目描述

给定一个非负整数数组和一个整数 m,你需要将这个数组分成 个非空的连续子数组。设计一个算法使得这 个子数组各自和的最大值最小。

注意:
数组长度 满足以下条件:

  • 1 ≤ n ≤ 1000
  • 1 ≤ m ≤ min(50, n)

示例:

输入:
nums = [7,2,5,10,8]
m = 2

输出:
18

解释:
一共有四种方法将nums分割为2个子数组。
其中最好的方式是将其分为[7,2,5][10,8],
因为此时这两个子数组各自的和的最大值为18,在所有情况中最小。

解法

Python3


Java

class Solution {
    public int splitArray(int[] nums, int m) {
        long l = 0, r = 0;
        for (int x : nums) {
            l = Math.max(l, x);
            r += x;
        }
        while (l < r) {
            long mid = l + r >>> 1;
            if (check(nums, m, mid)) r = mid;
            else l = mid + 1;
        }
        return (int) r;
    }

    private boolean check(int[] nums, int m, long cap) {
        int cnt = 1;
        long tot = 0;
        for (int x : nums) {
            tot += x;
            if (tot > cap) {
                ++cnt;
                tot = x;
            }
        }
        return cnt <= m;
    }
}


414. 第三大的数

English Version

题目描述

给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。

示例 1:

输入: [3, 2, 1]

输出: 1

解释: 第三大的数是 1.

示例 2:

输入: [1, 2]

输出: 2

解释: 第三大的数不存在, 所以返回最大的数 2 .

示例 3:

输入: [2, 2, 3, 1]

输出: 1

解释: 注意,要求返回第三大的数,是指第三大且唯一出现的数。
存在两个值为2的数,它们都排第二。

解法

Python3


Java

class Solution {
    public int thirdMax(int[] nums) {
        long m1 = Long.MIN_VALUE;
        long m2 = Long.MIN_VALUE;
        long m3 = Long.MIN_VALUE;
        for (int x : nums) {
            if (x == m1 || x == m2 || x == m3) {
                continue;
            }
            if (x > m1) {
                m3 = m2;
                m2 = m1;
                m1 = x;
            } else if (x > m2) {
                m3 = m2;
                m2 = x;
            } else if (x > m3) {
                m3 = x;
            }
        }
        return (int) (m3 != Long.MIN_VALUE ? m3 : m1);
    }
}


415. 字符串相加

English Version

题目描述

给定两个字符串形式的非负整数 num1num2 ,计算它们的和。

注意:

  1. num1num2 的长度都小于 5100.
  2. num1num2 都只包含数字 0-9.
  3. num1num2 都不包含任何前导零。
  4. 你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式。

解法

Python3


Java

class Solution {
    public String addStrings(String num1, String num2) {
        int i = num1.length() - 1;
        int j = num2.length() - 1;
        int carry = 0;
        StringBuilder res = new StringBuilder();
        while (i >= 0 || j >= 0 || carry != 0) {
            carry += (i >= 0 ? num1.charAt(i--) - '0' : 0) + (j >= 0 ? num2.charAt(j--) - '0' : 0);
            res.append(carry % 10);
            carry /= 10;
        }
        return res.reverse().toString();
    }
}


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

English Version

题目描述

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

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

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

示例:

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

输出: 28

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

解法

Python3


Java

class Solution {

    public int findMaximumXOR(int[] numbers) {
        int max = 0;
        int mask = 0;
        for (int i = 30; i >= 0; i--) {
            int current = 1 << i;
            // 期望的二进制前缀
            mask = mask ^ current;
            // 在当前前缀下, 数组内的前缀位数所有情况集合
            Set<Integer> set = new HashSet<>();
            for (int j = 0, k = numbers.length; j < k; j++) {
                set.add(mask & numbers[j]);
            }
            // 期望最终异或值的从右数第i位为1, 再根据异或运算的特性推算假设是否成立
            int flag = max | current;
            for (Integer prefix : set) {
                if (set.contains(prefix ^ flag)) {
                    max = flag;
                    break;
                }
            }
        }
        return max;
    }
}


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

English Version

题目描述

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:
字符串长度 和 k 不会超过 104

示例 1:

输入:
s = "ABAB", k = 2

输出:
4

解释:
用两个'A'替换为两个'B',反之亦然。

示例 2:

输入:
s = "AABABBA", k = 1

输出:
4

解释:
将中间的一个'A'替换为'B',字符串变为 "AABBBBA"。
子串 "BBBB" 有最长重复字母, 答案为 4。

解法

Python3


Java

class Solution {
    public int characterReplacement(String s, int k) {
        char[] cs = s.toCharArray();
        int[] map = new int[26];
        int res = 0;
        int max = 0;
        for (int l = 0, r = 0; r < cs.length; ) {
            max = Math.max(max, ++map[cs[r++] - 'A']);
            while (r - l - max > k) {
                --map[cs[l++] - 'A'];
            }
            res = Math.max(res, r - l);
        }
        return res;
    }
}


426. 将二叉搜索树转化为排序的双向链表

English Version

题目描述

将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表

对于双向循环列表,你可以将左右孩子指针作为双向循环链表的前驱和后继指针,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

特别地,我们希望可以 就地 完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中最小元素的指针。

示例 1:

输入:root = [4,2,5,1,3] 

在这里插入图片描述

输出:[1,2,3,4,5]

解释:下图显示了转化后的二叉搜索树,实线表示后继关系,虚线表示前驱关系。

在这里插入图片描述

示例 2:

输入:root = [2,1,3]
输出:[1,2,3]

示例 3:

输入:root = []
输出:[]
解释:输入是空树,所以输出也是空链表。

示例 4:

输入:root = [1]
输出:[1]

提示:

  • -1000 <= Node.val <= 1000
  • Node.left.val < Node.val < Node.right.val
  • Node.val 的所有值都是独一无二的
  • 0 <= Number of Nodes <= 2000

解法

  • 排序链表:二叉搜索树中序遍历得到有序序列
  • 循环链表:头节点指向链表尾节点,尾节点指向链表头节点
  • 双向链表:pre.right = curcur.left = prepre = cur

Python3

"""
# Definition for a Node.
class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
"""
class Solution:
    def treeToDoublyList(self, root: 'Node') -> 'Node':
        def dfs(cur):
            if cur is None:
                return
            dfs(cur.left)
            if self.pre is None:
                self.head = cur
            else:
                self.pre.right = cur
            cur.left = self.pre
            self.pre = cur
            dfs(cur.right)
        if root is None:
            return None
        self.head = self.pre = None
        dfs(root)
        self.head.left = self.pre
        self.pre.right = self.head
        return self.head

Java

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val,Node _left,Node _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/

class Solution {
    private Node head;
    private Node pre;

    public Node treeToDoublyList(Node root) {
        if (root == null) return null;
        dfs(root);
        head.left = pre;
        pre.right = head;
        return head;
    }

    private void dfs(Node cur) {
        if (cur == null) return;
        dfs(cur.left);
        if (pre == null) head = cur;
        else pre.right = cur;
        cur.left = pre;
        pre = cur;
        dfs(cur.right);
    }
}

JavaScript

/**
 * // Definition for a Node.
 * function Node(val,left,right) {
 *    this.val = val;
 *    this.left = left;
 *    this.right = right;
 * };
 */
/**
 * @param {Node} root
 * @return {Node}
 */
var treeToDoublyList = function (root) {
  function dfs(cur) {
    if (!cur) return;
    dfs(cur.left);
    if (!pre) head = cur;
    else pre.right = cur;
    cur.left = pre;
    pre = cur;
    dfs(cur.right);
  }
  if (!root) return null;
  let head, pre;
  dfs(root);
  head.left = pre;
  pre.right = head;
  return head;
};


430. 扁平化多级双向链表

English Version

题目描述

您将获得一个双向链表,除了下一个和前一个指针之外,它还有一个子指针,可能指向单独的双向链表。这些子列表可能有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。

扁平化列表,使所有结点出现在单级双链表中。您将获得列表第一级的头部。

 

示例:

输入:
 1---2---3---4---5---6--NULL
         |
         7---8---9---10--NULL
             |
             11--12--NULL

输出:
1-2-3-7-8-11-12-9-10-4-5-6-NULL

 

以上示例的说明:

给出以下多级双向链表:

在这里插入图片描述

 

我们应该返回如下所示的扁平双向链表:

在这里插入图片描述

解法

Python3


Java

class Solution {
    public Node flatten(Node head) {
        if (head == null) {
            return null;
        }
        dfs(head);
        head.prev = null;
        return head;
    }

    private Node dfs(Node head) {
        Node cur = head;
        while (cur != null) {
            head.prev = cur;
            Node next = cur.next;
            if (cur.child != null) {
                Node h = dfs(cur.child);
                cur.child = null;
                Node t = h.prev;
                cur.next = h;
                h.prev = cur;
                t.next = next;
                if (next != null) {
                    next.prev = t;
                }
                head.prev = t;
            }
            cur = next;
        }
        return head;
    }
}


437. 路径总和 III

English Version

题目描述

给定一个二叉树,它的每个结点都存放着一个整数值。

找出路径和等于给定数值的路径总数。

路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。

示例:

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

      10
     /  \
    5   -3
   / \    \
  3   2   11
 / \   \
3  -2   1

返回 3。和等于 8 的路径有:

1.  5 -> 3
2.  5 -> 2 -> 1
3.  -3 -> 11

解法

Python3


Java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public int pathSum(TreeNode root, int sum) {
        if (root == null) return 0;
        int res = 0;
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            res += solution(node, sum);
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
        return res;
    }

    private int solution(TreeNode root, int sum) {
        if (root == null) return 0;
        int res = sum == root.val ? 1 :
        return solution(root.left, sum - root.val) + solution(root.right, sum - root.val) + res;
    }
}


441. 排列硬币

English Version

题目描述

你总共有 枚硬币,你需要将它们摆成一个阶梯形状,第 行就必须正好有 枚硬币。

给定一个数字 n,找出可形成完整阶梯行的总行数。

是一个非负整数,并且在32位有符号整型的范围内。

示例 1:

n = 5

硬币可排列成以下几行:
¤
¤ ¤
¤ ¤

因为第三行不完整,所以返回2.

示例 2:

n = 8

硬币可排列成以下几行:
¤
¤ ¤
¤ ¤ ¤
¤ ¤

因为第四行不完整,所以返回3.

解法

(1 + x) * x / 2 <= n,求解 x。

(x + 1/2)² <= 2n + 1/4,即 x <= sqrt(2n + 1/4) - 1/2

由于 2n 可能溢出,故转换为 x <= sqrt(2) * sqrt(n + 1/8) - 1/2

Python3

class Solution:
    def arrangeCoins(self, n: int) -> int:
        return int(math.sqrt(2) * math.sqrt(n + 0.125) - 0.5)

Java

class Solution {
    public int arrangeCoins(int n) {
        return (int) (Math.sqrt(2) * Math.sqrt(n + 0.125) - 0.5);
    }
}


442. 数组中重复的数据

English Version

题目描述

给定一个整数数组 a,其中1 ≤ a[i] ≤ nn为数组长度), 其中有些元素出现两次而其他元素出现一次

找到所有出现两次的元素。

你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗?

示例:

输入:
[4,3,2,7,8,2,3,1]

输出:
[2,3]

解法

Python3


Java

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> ans = new ArrayList<>();
        for(int i = 0; i < nums.length; i++) {
            if(nums[i] != nums[nums[i] - 1]) {
                swap(nums, i, nums[i] - 1);
                i--;
            }
        }
        
        System.out.println(Arrays.toString(nums));
        
        for(int i = 0; i < nums.length; i++) {
            if(nums[i] != i + 1) {
                ans.add(nums[i]);
            }
        }
        
        return ans;
    }
    
    private void swap(int[] nums, int i, int j) {
		int tmp = nums[i];
		nums[i] = nums[j];
		nums[j] = tmp;
	}
}


445. 两数相加 II

English Version

题目描述

给定两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。

 

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

进阶:

如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。

示例:

输入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出: 7 -> 8 -> 0 -> 7

解法

Python3


Java

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Deque<Integer> s1 = new ArrayDeque<>();
        Deque<Integer> s2 = new ArrayDeque<>();
        for (; l1 != null; l1 = l1.next) {
            s1.push(l1.val);
        }
        for (; l2 != null; l2 = l2.next) {
            s2.push(l2.val);
        }
        ListNode head = null;
        int carry = 0;
        while (!s1.isEmpty() || !s2.isEmpty() || carry > 0) {
            carry += (s1.isEmpty() ? 0 : s1.pop()) + (s2.isEmpty() ? 0 : s2.pop());
            ListNode h = new ListNode(carry % 10);
            h.next = head;
            head = h;
            carry /= 10;
        }
        return head;
    }
}


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

English Version

题目描述

给定一个范围在  1 ≤ a[i] ≤ nn = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。

找到所有在 [1, n] 范围之间没有出现在数组中的数字。

您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。

示例:

输入:
[4,3,2,7,8,2,3,1]

输出:
[5,6]

解法

  • 遍历输入数组的每个元素一次。
  • |nums[i]|-1 索引位置的元素标记为负数。即 nums[|nums[i]|-1] * -1。
  • 然后遍历数组,若当前数组元素 nums[i] 为负数,说明我们在数组中存在数字 i+1。否则,说明数组不存在数字 i+1,添加到结果列表中。

Python3

class Solution:
    def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
        for num in nums:
            index = abs(num) - 1
            if nums[index] > 0:
                nums[index] *= -1
        res = []
        for i, v in enumerate(nums):
            if v > 0:
                res.append(i + 1)
        return res

Java

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        int n = nums.length;
        for (int i = 0; i < n; ++i) {
            int index = Math.abs(nums[i]) - 1;
            if (nums[index] > 0) {
                nums[index] *= -1;
            }
        }
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < n; ++i) {
            if (nums[i] > 0) {
                res.add(i + 1);
            }
        }
        return res;
    }
}


449. 序列化和反序列化二叉搜索树

English Version

题目描述

序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。

设计一个算法来序列化和反序列化二叉搜索树。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。

编码的字符串应尽可能紧凑。

注意:不要使用类成员/全局/静态变量来存储状态。 你的序列化和反序列化算法应该是无状态的。

解法

Python3


Java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            if (root == null) {
                return "";
            }
            StringBuilder sb = new StringBuilder();
            robot(root, sb);
            return sb.substring(0, sb.length() - 1);
        }

        private void robot(TreeNode root, StringBuilder sb) {
            if (root == null) {
                return;
            }
            sb.append(root.val).append(",");
            robot(root.left, sb);
            robot(root.right, sb);
        }

        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            if (data == null || Objects.equals(data, "")) {
                return null;
            }
            String[] pre = data.split(",");
            return build(pre, 0, pre.length - 1);
        }

        private TreeNode build(String[] pre, int start, int end) {
            if (start > end) {
                return null;
            }
            TreeNode root = new TreeNode(Integer.valueOf(pre[start]));

            int index = end + 1;
            for (int i = start + 1; i <= end; i++) {
                if (Integer.valueOf(pre[i]) > root.val) {
                    index = i;
                    break;
                }
            }

            root.left = build(pre, start + 1, index - 1);
            root.right = build(pre, index, end);
            return root;
        }

    }

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));


450. 删除二叉搜索树中的节点

English Version

题目描述

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

说明: 要求算法时间复杂度为 O(h),h 为树的高度。

示例:

root = [5,3,6,2,4,null,7]
key = 3

    5
   / \
  3   6
 / \   \
2   4   7

给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。

一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。

    5
   / \
  4   6
 /     \
2       7

另一个正确答案是 [5,2,6,null,4,null,7]。

    5
   / \
  2   6
   \   \
    4   7

解法

Python3


Java

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) {
            return null;
        }
        if (root.val > key) {
            root.left = deleteNode(root.left, key);
            return root;
        } else if (root.val < key) {
            root.right = deleteNode(root.right, key);
            return root;
        } else {
            if (root.left == null) return root.right;
            if (root.right == null) return root.left;
            TreeNode newRoot = root.right;
            TreeNode parent = null;
            while (newRoot.left != null) {
                parent = newRoot;
                newRoot = newRoot.left;
            }
            if (parent != null) {
                parent.left = newRoot.right;
                newRoot.right = root.right;
            }
            newRoot.left = root.left;
            return newRoot;
        }
    }
}


452. 用最少数量的箭引爆气球

English Version

题目描述

在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以y坐标并不重要,因此只要知道开始和结束的x坐标就足够了。开始坐标总是小于结束坐标。平面内最多存在104个气球。

一支弓箭可以沿着x轴从不同点完全垂直地射出。在坐标x处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足  xstart ≤ x ≤ xend,则该气球会被引爆可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。

Example:

输入:
[[10,16], [2,8], [1,6], [7,12]]

输出:
2

解释:
对于该样例,我们可以在x = 6(射爆[2,8],[1,6]两个气球)和 x = 11(射爆另外两个气球)。

解法

Python3


Java

class Solution {
    public int findMinArrowShots(int[][] points) {
        if (points == null || points.length == 0) {
            return 0;
        }
        Arrays.sort(points, Comparator.comparingInt(o -> o[1]));
        int res = 1;
        int pre = points[0][1];
        for (int i = 1; i < points.length; ++i) {
            if (points[i][0] > pre) {
                ++res;
                pre = points[i][1];
            }
        }
        return res;
    }
}


453. 最小移动次数使数组元素相等

English Version

题目描述

给定一个长度为 n非空整数数组,找到让数组所有元素相等的最小移动次数。每次移动可以使 n - 1 个元素增加 1。

示例:

输入:
[1,2,3]

输出:
3

解释:
只需要3次移动(注意每次移动会增加两个元素的值):

[1,2,3]  =>  [2,3,3]  =>  [3,4,3]  =>  [4,4,4]

解法

Python3


Java

class Solution {
    public int minMoves(int[] nums) {
        return Arrays.stream(nums).sum() - Arrays.stream(nums).min().getAsInt() * nums.length;
    }
}


454. 四数相加 II

English Version

题目描述

给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0

为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -228 到 228 - 1 之间,最终结果不会超过 231 - 1 。

例如:

输入:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]

输出:
2

解释:
两个元组如下:
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

解法

Python3


Java

class Solution {
    public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int a : A) {
            for (int b : B) {
                int key = a + b;
                map.put(key, map.getOrDefault(key, 0) + 1);
            }
        }
        int res = 0;
        for (int c : C) {
            for (int d : D) {
                res += map.getOrDefault(-(c + d), 0);
            }
        }
        return res;
    }
}


456. 132 模式

English Version

题目描述

给定一个整数序列:a1, a2, ..., an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj。设计一个算法,当给定有 n 个数字的序列时,验证这个序列中是否含有132模式的子序列。

注意:n 的值小于15000。

示例1:

输入: [1, 2, 3, 4]

输出: False

解释: 序列中不存在132模式的子序列。

示例 2:

输入: [3, 1, 4, 2]

输出: True

解释: 序列中有 1 个132模式的子序列: [1, 4, 2].

示例 3:

输入: [-1, 3, 2, 0]

输出: True

解释: 序列中有 3 个132模式的的子序列: [-1, 3, 2], [-1, 3, 0] 和 [-1, 2, 0].

解法

Python3


Java

class Solution {
    public boolean find132pattern(int[] nums) {
        int ak = Integer.MIN_VALUE;
        Deque<Integer> stack = new ArrayDeque<>();
        for (int i = nums.length - 1; i >= 0; --i) {
            if (nums[i] < ak) {
                return true;
            }
            while (!stack.isEmpty() && nums[i] > stack.peek()) {
                ak = stack.pop();
            }
            stack.push(nums[i]);
        }
        return false;
    }
}


458. 可怜的小猪

English Version

题目描述

有 1000 只水桶,其中有且只有一桶装的含有毒药,其余装的都是水。它们从外观看起来都一样。如果小猪喝了毒药,它会在 15 分钟内死去。

问题来了,如果需要你在一小时内,弄清楚哪只水桶含有毒药,你最少需要多少只猪?

回答这个问题,并为下列的进阶问题编写一个通用算法。

 

进阶:

假设有 n 只水桶,猪饮水中毒后会在 m 分钟内死亡,你需要多少猪(x)就能在 p 分钟内找出 “有毒” 水桶?这 n 只水桶里有且仅有一只有毒的桶。

 

提示:

  1. 可以允许小猪同时饮用任意数量的桶中的水,并且该过程不需要时间。
  2. 小猪喝完水后,必须有 m 分钟的冷却时间。在这段时间里,只允许观察,而不允许继续饮水。
  3. 任何给定的桶都可以无限次采样(无限数量的猪)。

解法

Python3


Java

class Solution {
    public int poorPigs(int buckets, int minutesToDie, int minutesToTest) {
        int base = minutesToTest / minutesToDie + 1;
        int res = 0;
        int p = 1;
        while (p < buckets) {
            p *= base;
            ++res;
        }
        return res;
    }
}


459. 重复的子字符串

English Version

题目描述

给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

示例 1:

输入: "abab"

输出: True

解释: 可由子字符串 "ab" 重复两次构成。

示例 2:

输入: "aba"

输出: False

示例 3:

输入: "abcabcabcabc"

输出: True

解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。)

解法

Python3


Java

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        String str = s + s;
        return str.substring(1, str.length() - 1).contains(s);
    }
}


461. 汉明距离

English Version

题目描述

两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。

给出两个整数 xy,计算它们之间的汉明距离。

注意:
0 ≤ x, y < 231.

示例:

输入: x = 1, y = 4

输出: 2

解释:
1   (0 0 0 1)
4   (0 1 0 0)
       ↑   ↑

上面的箭头指出了对应二进制位不同的位置。

解法

Python3


Java

class Solution {
    public int hammingDistance(int x, int y) {
        int count = 0, sum = x ^ y;
        while (sum != 0) {
            sum &= (sum - 1);
            count++;
        }
        return count;
    }
}


462. 最少移动次数使数组元素相等 II

English Version

题目描述

给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1。 您可以假设数组的长度最多为10000。

例如:

输入:
[1,2,3]

输出:
2

说明:
只有两个动作是必要的(记得每一步仅可使其中一个元素加1或减1): 

[1,2,3]  =>  [2,2,3]  =>  [2,2,2]

解法

Python3


Java

class Solution {
    public int minMoves2(int[] nums) {
        Arrays.sort(nums);
        int k = nums[nums.length / 2];
        int res = 0;
        for (int num : nums) {
            res += Math.abs(num - k);
        }
        return res;
    }
}


473. 火柴拼正方形

English Version

题目描述

还记得童话《卖火柴的小女孩》吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法。不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到。

输入为小女孩拥有火柴的数目,每根火柴用其长度表示。输出即为是否能用所有的火柴拼成正方形。

示例 1:

输入: [1,1,2,2,2]
输出: true

解释: 能拼成一个边长为2的正方形,每边两根火柴。

示例 2:

输入: [3,3,3,3,4]
输出: false

解释: 不能用所有火柴拼成一个正方形。

注意:

  1. 给定的火柴长度和在 0 到 10^9之间。
  2. 火柴数组的长度不超过15。

解法

Python3


Java

class Solution {
    public boolean makesquare(int[] nums) {
        if (nums == null || nums.length == 0) {
            return false;
        }
        int sum = Arrays.stream(nums).sum();
        if (sum % 4 != 0) {
            return false;
        }
        Arrays.sort(nums);
        int[] lens = new int[4];
        return dfs(nums, nums.length - 1, lens, sum / 4);
    }

    private boolean dfs(int[] nums, int index, int[] lens, int len) {
        if (lens[0] == len && lens[1] == len && lens[2] == len) {
            return true;
        }
        for (int i = 0; i < 4; ++i) {
            if (lens[i] + nums[index] <= len) {
                lens[i] += nums[index];
                if (dfs(nums, index - 1, lens, len)) {
                    return true;
                }
                lens[i] -= nums[index];
            }
        }
        return false;
    }
}


475. 供暖器

English Version

题目描述

冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。

现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径。

所以,你的输入将会是房屋和供暖器的位置。你将输出供暖器的最小加热半径。

说明:

  1. 给出的房屋和供暖器的数目是非负数且不会超过 25000。
  2. 给出的房屋和供暖器的位置均是非负数且不会超过10^9。
  3. 只要房屋位于供暖器的半径内(包括在边缘上),它就可以得到供暖。
  4. 所有供暖器都遵循你的半径标准,加热的半径也一样。

示例 1:

输入: [1,2,3],[2]
输出: 1
解释: 仅在位置2上有一个供暖器。如果我们将加热半径设为1,那么所有房屋就都能得到供暖。

示例 2:

输入: [1,2,3,4],[1,4]
输出: 1
解释: 在位置1, 4上有两个供暖器。我们需要将加热半径设为1,这样所有房屋就都能得到供暖。

解法

Python3


Java

class Solution {
    public int findRadius(int[] houses, int[] heaters) {
        Arrays.sort(heaters);
        int res = 0;
        for (int x : houses) {
            int i = Arrays.binarySearch(heaters, x);
            if (i < 0) {
                i = ~i;
            }
            int dis1 = i > 0 ? x - heaters[i - 1] : Integer.MAX_VALUE;
            int dis2 = i < heaters.length ? heaters[i] - x : Integer.MAX_VALUE;
            res = Math.max(res, Math.min(dis1, dis2));
        }
        return res;
    }
}


477. 汉明距离总和

English Version

题目描述

两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。

计算一个数组中,任意两个数之间汉明距离的总和。

示例:

输入: 4, 14, 2

输出: 6

解释: 在二进制表示中,4表示为0100,14表示为1110,2表示为0010。(这样表示是为了体现后四位之间关系)
所以答案为:
HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.

注意:

  1. 数组中元素的范围为从 0到 10^9
  2. 数组的长度不超过 10^4

解法

Python3


Java

class Solution {
    public int totalHammingDistance(int[] nums) {
        
        if (nums == null || nums.length < 2) {
			return 0;
		}
        
        int[] m = new int[31];// 存储对应位数,有多少个0
        for(int num : nums) {
        	for(int i = 0; i < 31; i++) {
        		if ((num & (1 << i)) == 0) {
					m[i]++;
				}
        	}
        }
        
        int result = 0;
        for(int i = 0; i < 31; i++) {
        	result += m[i] * (nums.length - m[i]);
        }
        
        return result;
    
    }
}


483. 最小好进制

English Version

题目描述

对于给定的整数 n, 如果n的k(k>=2)进制数的所有数位全为1,则称 k(k>=2)是 n 的一个好进制

以字符串的形式给出 n, 以字符串的形式返回 n 的最小好进制。

 

示例 1:

输入:"13"
输出:"3"
解释:13 的 3 进制是 111。

示例 2:

输入:"4681"
输出:"8"
解释:4681 的 8 进制是 11111。

示例 3:

输入:"1000000000000000000"
输出:"999999999999999999"
解释:1000000000000000000 的 999999999999999999 进制是 11。

 

提示:

  1. n的取值范围是 [3, 10^18]。
  2. 输入总是有效且没有前导 0。

 

解法

Python3


Java

class Solution {
    public String smallestGoodBase(String n) {
        long num = Long.parseLong(n);
        for (int len = 63; len >= 2; --len) {
            long radix = getRadix(len, num);
            if (radix != -1) {
                return String.valueOf(radix);
            }
        }
        return String.valueOf(num - 1);
    }

    private long getRadix(int len, long num) {
        long l = 2, r = num - 1;
        while (l < r) {
            long mid = l + r >>> 1;
            if (calc(mid, len) >= num) r = mid;
            else l = mid + 1;
        }
        return calc(r, len) == num ? r : -1;
    }

    private long calc(long radix, int len) {
        long p = 1;
        long sum = 0;
        for (int i = 0; i < len; ++i) {
            if (Long.MAX_VALUE - sum < p) {
                return Long.MAX_VALUE;
            }
            sum += p;
            if (Long.MAX_VALUE / p < radix) {
                p = Long.MAX_VALUE;
            } else {
                p *= radix;
            }
        }
        return sum;
    }
}


485. 最大连续 1 的个数

English Version

题目描述

给定一个二进制数组, 计算其中最大连续1的个数。

示例 1:

输入: [1,1,0,1,1,1]
输出: 3
解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3.

注意:

  • 输入的数组只包含 01
  • 输入数组的长度是正整数,且不超过 10,000。

解法

Python3

class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        res = t = 0
        for num in nums:
            if num == 1:
                t += 1
            else:
                res = max(res, t)
                t = 0
        return max(res, t)

Java

class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int res = 0, t = 0;
        for (int num : nums) {
            if (num == 1) {
                ++t;
            } else {
                res = Math.max(res, t);
                t = 0;
            }
        }
        return Math.max(res, t);
    }
}

JavaScript

/**
 * @param {number[]} nums
 * @return {number}
 */
var findMaxConsecutiveOnes = function (nums) {
  let res = 0,
    t = 0;
  for (let num of nums) {
    if (num == 1) {
      ++t;
    } else {
      res = Math.max(res, t);
      t = 0;
    }
  }
  return Math.max(res, t);
};


486. 预测赢家

English Version

题目描述

给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。

给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。

示例 1:

输入: [1, 5, 2]
输出: False
解释: 一开始,玩家1可以从1和2中进行选择。
如果他选择2(或者1),那么玩家2可以从1(或者2)和5中进行选择。如果玩家2选择了5,那么玩家1则只剩下1(或者2)可选。
所以,玩家1的最终分数为 1 + 2 = 3,而玩家2为 5。
因此,玩家1永远不会成为赢家,返回 False。

示例 2:

输入: [1, 5, 233, 7]
输出: True
解释: 玩家1一开始选择1。然后玩家2必须从5和7中进行选择。无论玩家2选择了哪个,玩家1都可以选择233。
最终,玩家1(234分)比玩家2(12分)获得更多的分数,所以返回 True,表示玩家1可以成为赢家。

注意:

  1. 1 <= 给定的数组长度 <= 20.
  2. 数组里所有分数都为非负数且不会大于10000000。
  3. 如果最终两个玩家的分数相等,那么玩家1仍为赢家。

解法

Python3


Java

class Solution {
    public boolean PredictTheWinner(int[] nums) {
        int n = nums.length;
        if ((n & 1) == 0) {
            return true;
        }
        int[] f = new int[n];
        for (int i = n - 1; i >= 0; --i) {
            f[i] = nums[i];
            for (int j = i + 1; j < n; ++j) {
                f[j] = Math.max(nums[i] - f[j], nums[j] - f[j - 1]);
            }
        }
        return f[n - 1] >= 0;
    }
}


487. 最大连续 1 的个数 II

English Version

题目描述

给定一个二进制数组,你可以最多将 1 个 0 翻转为 1,找出其中最大连续 1 的个数。

示例 1:

输入:[1,0,1,1,0]
输出:4
解释:翻转第一个 0 可以得到最长的连续 1。
     当翻转以后,最大连续 1 的个数为 4。

注:

  • 输入数组只包含 01.
  • 输入数组的长度为正整数,且不超过 10,000

进阶:
如果输入的数字是作为 无限流 逐个输入如何处理?换句话说,内存不能存储下所有从流中输入的数字。您可以有效地解决吗?

解法

prefix[i] 数组表示以 i 结尾往前累计的最大连续 1 的个数,suffix[i] 数组表示以 i 开头往后累计的最大连续 1 的个数。

遍历 nums 数组每个为 0 的位置,则位置 i 的最大连续 1 的个数为 1 + prefix[i-1] + suffix[i+1]

当然,如果 nums 数组没有 0,即所有元素都是 1,那么结果即为 nums 数组的长度。

Python3

class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        n = len(nums)
        prefix = [0] * n
        suffix = [0] * n
        res = 0
        for i in range(n):
            if i == 0:
                prefix[i] = nums[i]
            else:
                prefix[i] = 0 if nums[i] == 0 else prefix[i - 1] + 1
            res = max(res, prefix[i])

        for i in range(n - 1, -1, -1):
            if i == n - 1:
                suffix[i] = nums[i]
            else:
                suffix[i] = 0 if nums[i] == 0 else suffix[i + 1] + 1

        for i in range(n):
            if nums[i] == 0:
                t = 1
                if i > 0:
                    t += prefix[i - 1]
                if i < n - 1:
                    t += suffix[i + 1]
                res = max(res, t)
        return res

Java

  • 双指针,时间复杂度 O(n²),空间复杂度 O(1)
class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int n = nums.length;
        int res = 0;
        for (int i = 0; i < n; ++i) {
            int cnt = 1;
            int j = i;
            while (j < n && (cnt > 0 || nums[j] == 1)) {
                if (nums[j] == 0) --cnt;
                ++j;
            }
            res = Math.max(res, j - i);
        }
        return res;
    }
}
  • 辅助数组,时间复杂度 O(n),空间复杂度 O(n)
class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int n = nums.length;

        int[] prefix = new int[n];
        int[] suffix = new int[n];

        int res = 0;
        for (int i = 0; i < n; ++i) {
            if (i == 0) prefix[0] = nums[0];
            else prefix[i] = nums[i] == 0 ? 0 : prefix[i - 1] + 1;
            res = Math.max(res, prefix[i]);
        }

        for (int i = n - 1; i >= 0; --i) {
            if (i == n - 1) suffix[n - 1] = nums[n - 1];
            else suffix[i] = nums[i] == 0 ? 0 : suffix[i + 1] + 1;
        }

        for (int i = 0; i < n; ++i) {
            if (nums[i] == 0) {
                int t = 1;
                if (i > 0) t += prefix[i - 1];
                if (i < n - 1) t += suffix[i + 1];
                res = Math.max(res, t);
            }
        }
        return res;
    }
}


490. 迷宫

English Version

题目描述

由空地和墙组成的迷宫中有一个。球可以向上下左右四个方向滚动,但在遇到墙壁前不会停止滚动。当球停下时,可以选择下一个方向。

给定球的起始位置,目的地迷宫,判断球能否在目的地停下。

迷宫由一个0和1的二维数组表示。 1表示墙壁,0表示空地。你可以假定迷宫的边缘都是墙壁。起始位置和目的地的坐标通过行号和列号给出。

示例 1:

输入 1: 迷宫由以下二维数组表示

0 0 1 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 1 1
0 0 0 0 0

输入 2: 起始位置坐标 (rowStart, colStart) = (0, 4)
输入 3: 目的地坐标 (rowDest, colDest) = (4, 4)

输出: true

解析: 一个可能的路径是 : 左 -> 下 -> 左 -> 下 -> 右 -> 下 -> 右。

在这里插入图片描述

示例 2:

输入 1: 迷宫由以下二维数组表示

0 0 1 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 1 1
0 0 0 0 0

输入 2: 起始位置坐标 (rowStart, colStart) = (0, 4)
输入 3: 目的地坐标 (rowDest, colDest) = (3, 2)

输出: false

解析: 没有能够使球停在目的地的路径。

在这里插入图片描述

注意:

  1. 迷宫中只有一个球和一个目的地。
  2. 球和目的地都在空地上,且初始时它们不在同一位置。
  3. 给定的迷宫不包括边界 (如图中的红色矩形), 但你可以假设迷宫的边缘都是墙壁。
  4. 迷宫至少包括2块空地,行数和列数均不超过100。

解法

深度优先搜索或广度优先搜索实现。

Python3

深度优先搜索。

class Solution:
    def hasPath(self, maze: List[List[int]], start: List[int], destination: List[int]) -> bool:
        def dfs(maze, start, destination):
            if visited[start[0]][start[1]]:
                return False
            if start[0] == destination[0] and start[1] == destination[1]:
                return True
            visited[start[0]][start[1]] = True
            l, r, u, d = start[1] - 1, start[1] + 1, start[0] - 1, start[0] + 1
            while l >= 0 and maze[start[0]][l] == 0:
                l -= 1
            if dfs(maze, [start[0], l + 1], destination):
                return True
            while r < len(maze[0]) and maze[start[0]][r] == 0:
                r += 1
            if dfs(maze, [start[0], r - 1], destination):
                return True
            while u >= 0 and maze[u][start[1]] == 0:
                u -= 1
            if dfs(maze, [u + 1, start[1]], destination):
                return True
            while d < len(maze) and maze[d][start[1]] == 0:
                d += 1
            if dfs(maze, [d - 1, start[1]], destination):
                return True
            return False

        visited = [[False for _ in maze[0]] for _ in maze]
        return dfs(maze, start, destination)

Java

class Solution {
    private boolean[][] visited;

    public boolean hasPath(int[][] maze, int[] start, int[] destination) {
        int m = maze.length, n = maze[0].length;
        visited = new boolean[m][n];
        return dfs(maze, start, destination);
    }

    private boolean dfs(int[][] maze, int[] start, int[] destination) {
        if (visited[start[0]][start[1]]) return false;
        if (start[0] == destination[0] && start[1] == destination[1]) return true;
        visited[start[0]][start[1]] = true;

        int l = start[1] - 1, r = start[1] + 1, u = start[0] - 1, d = start[0] + 1;

        while (l >= 0 && maze[start[0]][l] == 0) --l;
        if (dfs(maze, new int[]{start[0], l + 1}, destination)) return true;

        while (r < maze[0].length && maze[start[0]][r] == 0) ++r;
        if (dfs(maze, new int[]{start[0], r - 1}, destination)) return true;

        while (u >= 0 && maze[u][start[1]] == 0) --u;
        if (dfs(maze, new int[]{u + 1, start[1]}, destination)) return true;

        while (d < maze.length && maze[d][start[1]] == 0) ++d;
        if (dfs(maze, new int[]{d - 1, start[1]}, destination)) return true;

        return false;
    }
}


492. 构造矩形

English Version

题目描述

作为一位web开发者, 懂得怎样去规划一个页面的尺寸是很重要的。 现给定一个具体的矩形页面面积,你的任务是设计一个长度为 L 和宽度为 W 且满足以下要求的矩形的页面。要求:

1. 你设计的矩形页面必须等于给定的目标面积。

2. 宽度 W 不应大于长度 L,换言之,要求 L >= W 。

3. 长度 L 和宽度 W 之间的差距应当尽可能小。

你需要按顺序输出你设计的页面的长度 L 和宽度 W。

示例:

输入: 4
输出: [2, 2]
解释: 目标面积是 4, 所有可能的构造方案有 [1,4], [2,2], [4,1]。
但是根据要求2,[1,4] 不符合要求; 根据要求3,[2,2] 比 [4,1] 更能符合要求. 所以输出长度 L 为 2, 宽度 W 为 2。

说明:

  1. 给定的面积不大于 10,000,000 且为正整数。
  2. 你设计的页面的长度和宽度必须都是正整数。

解法

Python3

class Solution:
    def constructRectangle(self, area: int) -> List[int]:
        sr = int(math.sqrt(area))
        l = w = sr
        while l <= area and w >= 1:
            s = l * w
            if s == area:
                break
            if s > area:
                w -= 1
            else:
                l += 1
        return [l, w]

Java

class Solution {
    public int[] constructRectangle(int area) {
        int sr = (int) Math.sqrt(area);
        int l = sr, w = sr;
        while (l <= area && w >= 1) {
            int s = l * w;
            if (s == area) break;
            if (s > area) --w;
            else ++l;
        }
        return new int[]{l, w};
    }
}


494. 目标和

English Version

题目描述

给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

示例 1:

输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释: 

-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3

一共有5种方法让最终目标和为3。

注意:

  1. 数组非空,且长度不会超过20。
  2. 初始的数组的和不会超过1000。
  3. 保证返回的最终结果能被32位整数存下。

解法

Python3


Java

class Solution {
    public int findTargetSumWays(int[] nums, int S) {
        int[] ans = new int[1];
        wayDfs(nums, 0, S, ans);
        return ans[0];
    }

    private void wayDfs(int[] nums, int start, int left, int[] ans) {
        if (start == nums.length) {
            if (left == 0) ans[0]++;
            return;
        }

        wayDfs(nums, start + 1, left + nums[start], ans);
        wayDfs(nums, start + 1, left - nums[start], ans);
    }
}


496. 下一个更大元素 I

English Version

题目描述

给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 大的元素。如果不存在,对应位置输出-1。

示例 1:

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
    对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
    对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
    对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。

示例 2:

输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
    对于num1中的数字2,第二个数组中的下一个较大数字是3。
    对于num1中的数字4,第二个数组中没有下一个更大的数字,因此输出 -1。

注意:

  1. nums1nums2中所有元素是唯一的。
  2. nums1nums2 的数组大小都不超过1000。

解法

Python3


Java

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        Deque<Integer> stack = new ArrayDeque<>();
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums2) {
            while (!stack.isEmpty() && num > stack.peek()) {
                map.put(stack.pop(), num);
            }
            stack.push(num);
        }
        int[] res = new int[nums1.length];
        for (int i = 0; i < nums1.length; ++i) {
            res[i] = map.getOrDefault(nums1[i], -1);
        }
        return res;
    }
}


500. 键盘行

English Version

题目描述

给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词。键盘如下图所示。

 

在这里插入图片描述

 

示例:

输入: ["Hello", "Alaska", "Dad", "Peace"]

输出: ["Alaska", "Dad"]

 

注意:

  1. 你可以重复使用键盘上同一字符。
  2. 你可以假设输入的字符串将只包含字母。

解法

Python3


Java

class Solution {

    public String[] findWords(String[] words) {
        if (words == null) {
            return null;
        }
        ArrayList<String> list = new ArrayList<>();
        String[] keyboards = {"qwertyuiop", "asdfghjkl", "zxcvbnm"};
        for (int i = 0; i < words.length; i++) {
            String word = words[i].toLowerCase();
            for (int j = 0; j < keyboards.length; j++) {
                // 先用word首字符确定属于哪一行
                if (keyboards[j].indexOf(word.charAt(0)) > -1) {
                    // 判断word字符串所有字符是否都属于同一行
                    boolean match = match(keyboards[j], word, list);
                    if (match) {
                        list.add(words[i]);
                    }
                    break;
                }
            }
        }
        return list.toArray(new String[list.size()]);
    }

    private boolean match(String keyboard, String word, ArrayList<String> list) {
        for (int i = 1; i < word.length(); i++) {
            if (keyboard.indexOf(word.charAt(i)) < 0) {
                return false;
            }
        }
        return true;
    }
}


501. 二叉搜索树中的众数

English Version

题目描述

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

  • 结点左子树中所含结点的值小于等于当前结点的值
  • 结点右子树中所含结点的值大于等于当前结点的值
  • 左子树和右子树都是二叉搜索树

例如:
给定 BST [1,null,2,2],

   1
    \
     2
    /
   2

返回[2].

提示:如果众数超过1个,不需考虑输出顺序

进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)

解法

Python3


Java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int max = 0;
    int cur = 0;
    TreeNode preNode = null;

    public int[] findMode(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        findMode(root, list);
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            res[i] = list.get(i);
        }
        return res;
    }

    private void findMode(TreeNode root, ArrayList<Integer> list) {
        if (root == null) {
            return;
        }
        findMode(root.left, list);
        if (preNode != null && root.val == preNode.val) {
            cur++;
        } else {
            cur = 1;
        }
        if (max < cur) {
            max = cur;
            list.clear();
            list.add(root.val);
        } else if (max == cur) {
            list.add(root.val);
        }
        preNode = root;
        findMode(root.right, list);
    }
}


502. IPO

English Version

题目描述

假设 力扣(LeetCode)即将开始其 IPO。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k 个不同的项目。帮助 力扣 设计完成最多 k 个不同项目后得到最大总资本的方式。

给定若干个项目。对于每个项目 i,它都有一个纯利润 Pi,并且需要最小的资本 Ci 来启动相应的项目。最初,你有 W 资本。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。

总而言之,从给定项目中选择最多 k 个不同项目的列表,以最大化最终资本,并输出最终可获得的最多资本。

示例 1:

输入: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1].

输出: 4

解释:
由于你的初始资本为 0,你尽可以从 0 号项目开始。
在完成后,你将获得 1 的利润,你的总资本将变为 1。
此时你可以选择开始 1 号或 2 号项目。
由于你最多可以选择两个项目,所以你需要完成 2 号项目以获得最大的资本。
因此,输出最后最大化的资本,为 0 + 1 + 3 = 4。

 

注意:

  1. 假设所有输入数字都是非负整数。
  2. 表示利润和资本的数组的长度不超过 50000。
  3. 答案保证在 32 位有符号整数范围内。

 

解法

Python3


Java

class Solution {
    /**
     * 贪心算法
     */
    public int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
        // 首先检查是否存在所有项目都可投资且初始资本 W >= max(Capital) 的情况。如果是,返回利润中前 k 个最大元素的和。
        boolean speedUp = true;
        for (int c : Capital) if (W < c) speedUp = false;
        if (speedUp) {
            PriorityQueue<Integer> heap = new PriorityQueue<>();
            for (int p : Profits) {
                heap.add(p);
                if (heap.size() > k) heap.poll();
            }
            for (int h : heap) W += h;
            return W;
        }

        int idx;
        int n = Profits.length;
        for (int i = 0; i < Math.min(k, n); ++i) {
            idx = -1;
            // 找到获取利润最多的项目
            for (int j = 0; j < n; ++j) {
                if (W >= Capital[j]) {
                    if (idx == -1) idx = j;
                    else if (Profits[idx] < Profits[j]) idx = j;
                }
            }
            // 找不到合适的项目
            if (idx == -1) break;
            // 累计当前项目的利润到总利润中,并把当前项目标记为"不可用"(设置成最大整数)
            W += Profits[idx];
            Capital[idx] = Integer.MAX_VALUE;
        }
        return W;
    }
} 


503. 下一个更大元素 II

English Version

题目描述

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

示例 1:

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

注意: 输入数组的长度不会超过 10000。

解法

Python3


Java

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int n = nums.length;
        int len = (n << 1) - 1;
        int[] res = new int[n];
        Deque<Integer> stack = new ArrayDeque<>();
        for (int i = 0; i < len; ++i) {
            int x = nums[i < n ? i : i - n];
            while (!stack.isEmpty() && x > nums[stack.peek()]) {
                res[stack.pop()] = x;
            }
            if (i < n) {
                stack.push(i);
            }
        }
        while (!stack.isEmpty()) {
            res[stack.pop()] = -1;
        }
        return res;
    }
}


504. 七进制数

English Version

题目描述

给定一个整数,将其转化为7进制,并以字符串形式输出。

示例 1:

输入: 100
输出: "202"

示例 2:

输入: -7
输出: "-10"

注意: 输入范围是 [-1e7, 1e7] 。

解法

Python3


Java

class Solution {
    public String convertToBase7(int num) {
        if (num == 0) {
            return "0";
        }
        if (num < 0) {
            return "-" + convertToBase7(-num);
        }
        StringBuilder sb = new StringBuilder();
        while (num != 0) {
            sb.append(num % 7);
            num /= 7;
        }
        return sb.reverse().toString();
    }
}


506. 相对名次

English Version

题目描述

给出 N 名运动员的成绩,找出他们的相对名次并授予前三名对应的奖牌。前三名运动员将会被分别授予 “金牌”,“银牌” 和“ 铜牌”("Gold Medal", "Silver Medal", "Bronze Medal")。

(注:分数越高的选手,排名越靠前。)

示例 1:

输入: [5, 4, 3, 2, 1]
输出: ["Gold Medal", "Silver Medal", "Bronze Medal", "4", "5"]
解释: 前三名运动员的成绩为前三高的,因此将会分别被授予 “金牌”,“银牌”和“铜牌” ("Gold Medal", "Silver Medal" and "Bronze Medal").
余下的两名运动员,我们只需要通过他们的成绩计算将其相对名次即可。

提示:

  1. N 是一个正整数并且不会超过 10000。
  2. 所有运动员的成绩都不相同。

解法

Python3


Java

class Solution {
    public String[] findRelativeRanks(int[] nums) {
        int n = nums.length;
        Integer[] index = new Integer[n];
        for (int i = 0; i < n; ++i) {
            index[i] = i;
        }
        Arrays.sort(index, (o1, o2) -> Integer.compare(nums[o2], nums[o1]));
        String[] res = new String[n];
        for (int i = 0; i < n; ++i) {
            if (i == 0) {
                res[index[i]] = "Gold Medal";
            } else if (i == 1) {
                res[index[i]] = "Silver Medal";
            } else if (i == 2) {
                res[index[i]] = "Bronze Medal";
            } else {
                res[index[i]] = String.valueOf(i + 1);
            }
        }
        return res;
    }
}


507. 完美数

English Version

题目描述

对于一个 正整数,如果它和除了它自身以外的所有正因子之和相等,我们称它为“完美数”。

给定一个 整数 n, 如果他是完美数,返回 True,否则返回 False

 

示例:

输入: 28
输出: True
解释: 28 = 1 + 2 + 4 + 7 + 14

 

提示:

输入的数字 n 不会超过 100,000,000. (1e8)

解法

Python3


Java

public class Solution {
    public boolean checkPerfectNumber(int num) {
        if (num == 0 || num == 1) {
            return false;
        }
        int sum = 1;
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) {
                sum = sum + i + num / i;
            }
        }
        return num == sum;
    }
}


508. 出现次数最多的子树元素和

English Version

题目描述

给出二叉树的根,找出出现次数最多的子树元素和。一个结点的子树元素和定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身)。然后求出出现次数最多的子树元素和。如果有多个元素出现的次数相同,返回所有出现次数最多的元素(不限顺序)。

 

示例 1
输入:

  5
 /  \
2   -3

返回 [2, -3, 4],所有的值均只出现一次,以任意顺序返回所有值。

示例 2
输入:

  5
 /  \
2   -5

返回 [2],只有 2 出现两次,-5 只出现 1 次。

 

提示: 假设任意子树元素和均可以用 32 位有符号整数表示。

解法

Python3


Java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    // 后续遍历,遍历的同时,找最大值和计算次数
    Map<Integer, Integer> map = new HashMap<>();
    int max = Integer.MIN_VALUE;

    public int[] findFrequentTreeSum(TreeNode root) {
        if (root == null) {
            return new int[0];
        }
        dfs(root);
        List<Integer> list = map.entrySet().stream()
                .filter(m -> m.getValue() == max).map(i -> i.getKey()).collect(Collectors.toList());
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            res[i] = list.get(i);
        }
        return res;
    }

    private int dfs(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = dfs(root.left);
        int right = dfs(root.right);
        int sum = root.val + left + right;
        int current = map.getOrDefault(sum, 0) + 1;
        map.put(sum, current);
        max = Math.max(current, max);
        return sum;
    }
}


509. 斐波那契数

English Version

题目描述

斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 01 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

给定 N,计算 F(N)

 

示例 1:

输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1.

示例 2:

输入:3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2.

示例 3:

输入:4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3.

 

提示:

  • 0 ≤ N ≤ 30

解法

Python3


Java

class Solution {
    public int fib(int N) {
        if (N < 2) {
            return N;
        }
        int a = 0, b = 1;
        int res = 0;
        for (int i = 2; i <= N; ++i) {
            res = a + b;
            a = b;
            b = res;
        }
        return res;
    }
}


513. 找树左下角的值

English Version

题目描述

给定一个二叉树,在树的最后一行找到最左边的值。

示例 1:

输入:

    2
   / \
  1   3

输出:
1

 

示例 2:

输入:

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

输出:
7

 

注意: 您可以假设树(即给定的根节点)不为 NULL

解法

Python3


Java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 * int val;
 * TreeNode left;
 * TreeNode right;
 * TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int max = -1;
    int value = 0;

    public int findBottomLeftValue(TreeNode root) {
        dfs(root, 0);
        return value;
    }

    private void dfs(TreeNode root, int d) {
        if (root == null) {
            return;
        }
        d++;
        if (max < d) {
            max = d;
            value = root.val;
        }
        dfs(root.left, d);
        dfs(root.right, d);
    }
}


515. 在每个树行中找最大值

English Version

题目描述

您需要在二叉树的每一行中找到最大的值。

示例:

输入: 

          1
         / \
        3   2
       / \   \  
      5   3   9 

输出: [1, 3, 9]

解法

Python3


Java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *      int val;
 *      TreeNode left;
 *      TreeNode right;
 *      TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    // 深度遍历
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        dfs(list, root, 0);
        return list;
    }

    private void dfs(List<Integer> list, TreeNode root, int level) {
        if (root == null) {
            return;
        }
        // 每深入一层,先把那一层的第一个节点加入返回 list中
        if (list.size() == level) {
            list.add(root.val);
        }
        // 此时 size > level ,那么就是开始遍历每一层 的 其他节点(不包括最左边的节点),
        // 直接比较list的对应下标(index)的值与当前值就好
        else {
            list.set(level, Math.max(list.get(level), root.val));
        }
        // 左右子树,深度要+1
        dfs(list, root.left, level + 1);
        dfs(list, root.right, level + 1);
    }
}


518. 零钱兑换 II

English Version

题目描述

给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 

 

    示例 1:

    输入: amount = 5, coins = [1, 2, 5]
    输出: 4
    解释: 有四种方式可以凑成总金额:
    5=5
    5=2+2+1
    5=2+1+1+1
    5=1+1+1+1+1
    

    示例 2:

    输入: amount = 3, coins = [2]
    输出: 0
    解释: 只用面额2的硬币不能凑成总金额3。
    

    示例 3:

    输入: amount = 10, coins = [10] 
    输出: 1
    

     

    注意:

    你可以假设:

    • 0 <= amount (总金额) <= 5000
    • 1 <= coin (硬币面额) <= 5000
    • 硬币种类不超过 500 种
    • 结果符合 32 位符号整数

    解法

    Python3

    
    

    Java

    class Solution {
        public int change(int amount, int[] coins) {
            int[] f = new int[amount + 1];
            f[0] = 1;
            for (int coin : coins) {
                for (int i = coin; i <= amount; ++i) {
                    f[i] += f[i - coin];
                }
            }
            return f[amount];
        }
    }
    
    

    
    

    520. 检测大写字母

    English Version

    题目描述

    给定一个单词,你需要判断单词的大写使用是否正确。

    我们定义,在以下情况时,单词的大写用法是正确的:

    1. 全部字母都是大写,比如"USA"。
    2. 单词中所有字母都不是大写,比如"leetcode"。
    3. 如果单词不只含有一个字母,只有首字母大写, 比如 "Google"。

    否则,我们定义这个单词没有正确使用大写字母。

    示例 1:

    输入: "USA"
    输出: True
    

    示例 2:

    输入: "FlaG"
    输出: False
    

    注意: 输入是由大写和小写拉丁字母组成的非空单词。

    解法

    Python3

    
    

    Java

    class Solution {
        public boolean detectCapitalUse(String word) {
            char[] cs = word.toCharArray();
            int upper = 0;
            int lower = 0;
            for (int i = 0; i < cs.length; i++) {
                if (cs[i] >= 'a') {
                    lower++;
                } else {
                    upper++;
                }
            }
            if (upper == cs.length) {
                return true;
            }
            if (lower == cs.length) {
                return true;
            }
            if (upper == 1 && cs[0] < 'a') {
                return true;
            }
            return false;
        }
    }
    
    

    
    

    521. 最长特殊序列 Ⅰ

    English Version

    题目描述

    给定两个字符串,你需要从这两个字符串中找出最长的特殊序列。最长特殊序列定义如下:该序列为某字符串独有的最长子序列(即不能是其他字符串的子序列)。

    子序列可以通过删去字符串中的某些字符实现,但不能改变剩余字符的相对顺序。空序列为所有字符串的子序列,任何字符串为其自身的子序列。

    输入为两个字符串,输出最长特殊序列的长度。如果不存在,则返回 -1。

    示例 :

    输入: "aba", "cdc"
    输出: 3
    解析: 最长特殊序列可为 "aba" (或 "cdc")
    

    说明:

    1. 两个字符串长度均小于100。
    2. 字符串中的字符仅含有 'a'~'z'。

    解法

    Python3

    
    

    Java

    class Solution {
        public int findLUSlength(String a, String b) {
            if (a.equals(b))
                return -1;
            return Math.max(a.length(), b.length());
        }
    }
    
    

    
    

    522. 最长特殊序列 II

    English Version

    题目描述

    给定字符串列表,你需要从它们中找出最长的特殊序列。最长特殊序列定义如下:该序列为某字符串独有的最长子序列(即不能是其他字符串的子序列)。

    子序列可以通过删去字符串中的某些字符实现,但不能改变剩余字符的相对顺序。空序列为所有字符串的子序列,任何字符串为其自身的子序列。

    输入将是一个字符串列表,输出是最长特殊序列的长度。如果最长特殊序列不存在,返回 -1 。

     

    示例:

    输入: "aba", "cdc", "eae"
    输出: 3
    

     

    提示:

    1. 所有给定的字符串长度不会超过 10 。
    2. 给定字符串列表的长度将在 [2, 50 ] 之间。

     

    解法

    Python3

    
    

    Java

    class Solution {
        public int findLUSlength(String[] strs) {
            int res = -1;
            if (strs == null || strs.length == 0) {
                return res;
            }
            if (strs.length == 1) {
                return strs[0].length();
            }
            // 两两比较
            // 1、存在子串,直接不比较后面的字符串
            // 2、不存在子串,判断当前字符串是否是最长的字符串
            for (int i = 0, j; i < strs.length; i++) {
                for (j = 0; j < strs.length; j++) {
                    if (i == j) {
                        continue;
                    }
                    // 根据题意,子串 可以 不是 原字符串中 连续的子字符串
                    if (isSubsequence(strs[i], strs[j])) {
                        break;
                    }
                }
                if (j == strs.length) {
                    res = Math.max(res, strs[i].length());
                }
            }
            return res;
        }
    
        public boolean isSubsequence(String x, String y) {
            int j = 0;
            for (int i = 0; i < y.length() && j < x.length(); i++) {
                if (x.charAt(j) == y.charAt(i))
                    j++;
            }
            return j == x.length();
        }
    }
    
    

    
    

    523. 连续的子数组和

    English Version

    题目描述

    给定一个包含非负数的数组和一个目标整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数

    示例 1:

    输入: [23,2,4,6,7], k = 6
    输出: True
    解释: [2,4] 是一个大小为 2 的子数组,并且和为 6。
    

    示例 2:

    输入: [23,2,6,4,7], k = 6
    输出: True
    解释: [23,2,6,4,7]是大小为 5 的子数组,并且和为 42。
    

    说明:

    1. 数组的长度不会超过10,000。
    2. 你可以认为所有数字总和在 32 位有符号整数范围内。

    解法

    Python3

    
    

    Java

    class Solution {
        public boolean checkSubarraySum(int[] nums, int k) {
    		for (int start = 0; start < nums.length; start++) {
            	int check = 0;
            	for (int i = start; i < nums.length; i++) {
            		check += nums[i];
                    if (i > start) {
                    	if (k != 0) {
                			if (check % k == 0) {
                        		return true;
                        	}
                		} else {
                			if (check == k) {
                				return true;
                			}
                		}
            		}
            	}
            }
            
            return false;
        }
    }
    

    
    

    525. 连续数组

    English Version

    题目描述

    给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组(的长度)。

     

    示例 1:

    输入: [0,1]
    输出: 2
    说明: [0, 1] 是具有相同数量0和1的最长连续子数组。

    示例 2:

    输入: [0,1,0]
    输出: 2
    说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。

     

    注意: 给定的二进制数组的长度不会超过50000。

    解法

    Python3

    
    

    Java

    class Solution {
        public int findMaxLength(int[] nums) {
            Map<Integer, Integer> map = new HashMap<>();
            map.put(0, -1);
            int res = 0;
            int s = 0;
            for (int i = 0; i < nums.length; ++i) {
                s += nums[i] == 1 ? 1 : -1;
                if (map.containsKey(s)) {
                    res = Math.max(res, i - map.get(s));
                } else {
                    map.put(s, i);
                }
            }
            return res;
        }
    }
    
    

    
    

    526. 优美的排列

    English Version

    题目描述

    假设有从 1 到 N 的 个整数,如果从这 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列。条件:

    1. 第 位的数字能被 整除
    2. i 能被第 i 位上的数字整除

    现在给定一个整数 N,请问可以构造多少个优美的排列?

    示例1:

    输入: 2
    输出: 2
    解释: 
    
    第 1 个优美的排列是 [1, 2]:
      第 1 个位置(i=1)上的数字是1,1能被 i(i=1)整除
      第 2 个位置(i=2)上的数字是2,2能被 i(i=2)整除
    
    第 2 个优美的排列是 [2, 1]:
      第 1 个位置(i=1)上的数字是2,2能被 i(i=1)整除
      第 2 个位置(i=2)上的数字是1,i(i=2)能被 1 整除
    

    说明:

    1. N 是一个正整数,并且不会超过15。

    解法

    Python3

    
    

    Java

    class Solution {
        public int countArrangement(int N) {
            int maxn = 1 << N;
            int[] f = new int[maxn];
            f[0] = 1;
            for (int i = 0; i < maxn; ++i) {
                int s = 1;
                for (int j = 0; j < N; ++j) {
                    s += (i >> j) & 1;
                }
                for (int j = 1; j <= N; ++j) {
                    if (((i >> (j - 1) & 1) == 0) && (s % j == 0 || j % s == 0)) {
                        f[i | (1 << (j - 1))] += f[i];
                    }
                }
            }
            return f[maxn - 1];
        }
    }
    
    

    
    

    530. 二叉搜索树的最小绝对差

    English Version

    题目描述

    给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。

     

    示例:

    输入:
    
       1
        \
         3
        /
       2
    
    输出:
    1
    
    解释:
    最小绝对差为 1,其中 2 和 1 的差的绝对值为 1(或者 2 和 3)。
    

     

    提示:

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public int getMinimumDifference(TreeNode root) {
            Integer res = Integer.MAX_VALUE, prev = Integer.MAX_VALUE;
            Stack<TreeNode> stack = new Stack<>();
            while (true) {
                while (root != null) {
                    stack.push(root);
                    root = root.left;
                }
                if (stack.isEmpty()) break;
                TreeNode node = stack.pop();
                res = Math.min(res, Math.abs(node.val - prev));
                prev = node.val;
                root = node.right;
            }
            return res;
        }
    }
    

    Go

    var res int
    var preNode *TreeNode
    func getMinimumDifference(root *TreeNode) int {
        res = int(^uint(0) >> 1)
        preNode = nil
        helper(root)
        return res
    }
    
    func helper(root *TreeNode)  {
        if root == nil {
            return
        }
        helper(root.Left)
        if preNode != nil {
            res = getMinInt(res, root.Val - preNode.Val)
        }
        preNode = root
        helper(root.Right)
    }
    
    func getMinInt(a,b int) int {
        if a < b {
            return a
        }
        return b
    }
    

    538. 把二叉搜索树转换为累加树

    English Version

    题目描述

    给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。

     

    例如:

    输入: 原始二叉搜索树:
                  5
                /   \
               2     13
    
    输出: 转换为累加树:
                 18
                /   \
              20     13
    

     

    注意:本题和 1038: https://leetcode-cn.com/problems/binary-search-tree-to-greater-sum-tree/ 相同

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        int add = 0;
        public TreeNode convertBST(TreeNode root) {
            if (root != null) {
                convertBST(root.right);
                root.val += add;
                add = root.val;
                convertBST(root.left);
            }
            return root;
        }
    }
    

    
    

    541. 反转字符串 II

    English Version

    题目描述

    给定一个字符串和一个整数 k,你需要对从字符串开头算起的每个 2k 个字符的前k个字符进行反转。如果剩余少于 k 个字符,则将剩余的所有全部反转。如果有小于 2k 但大于或等于 k 个字符,则反转前 k 个字符,并将剩余的字符保持原样。

    示例:

    输入: s = "abcdefg", k = 2
    输出: "bacdfeg"
    

    要求:

    1. 该字符串只包含小写的英文字母。
    2. 给定字符串的长度和 k 在[1, 10000]范围内。

    解法

    Python3

    
    

    Java

    class Solution {
        public String reverseStr(String s, int k) {
            if (k < 2) return s;
            StringBuilder sb = new StringBuilder();
            int length = s.length(), index = 0;
            while (index < length) {
                if (index + 2 * k <= length) {
                    sb.append(reverse(s, index, index + k));
                    sb.append(s.substring(index + k, index + 2 * k));
                    index += 2 * k;
                } else if (index + k <= length){
                    sb.append(reverse(s, index, index + k));
                    sb.append(s.substring(index + k));
                    break;
                } else {
                    sb.append(reverse(s, index, length));
                    break;
                }
            }
            return sb.toString();
        }
    
        private StringBuffer reverse(String s, int index, int end) {
            return new StringBuffer(s.substring(index, end)).reverse();
        }
    }
    

    
    

    542. 01 矩阵

    English Version

    题目描述

    给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。

    两个相邻元素间的距离为 1 。

    示例 1:
    输入:

    0 0 0
    0 1 0
    0 0 0
    

    输出:

    0 0 0
    0 1 0
    0 0 0
    

    示例 2:
    输入:

    0 0 0
    0 1 0
    1 1 1
    

    输出:

    0 0 0
    0 1 0
    1 2 1
    

    注意:

    1. 给定矩阵的元素个数不超过 10000。
    2. 给定矩阵中至少有一个元素是 0。
    3. 矩阵中的元素只在四个方向上相邻: 上、下、左、右。

    解法

    Python3

    
    

    Java

    class Solution {
        public int[][] updateMatrix(int[][] matrix) {
            int m = matrix.length, n = matrix[0].length;
            int[][] res = new int[m][n];
            for (int[] arr : res) {
                Arrays.fill(arr, -1);
            }
            class Position {
                int x, y;
    
                public Position(int x, int y) {
                    this.x = x;
                    this.y = y;
                }
            }
            Queue<Position> queue = new ArrayDeque<>();
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (matrix[i][j] == 0) {
                        res[i][j] = 0;
                        queue.offer(new Position(i, j));
                    }
                }
            }
            int[] dirs = new int[]{-1, 0, 1, 0, -1};
            while (!queue.isEmpty()) {
                Position pos = queue.poll();
                for (int i = 0; i < 4; ++i) {
                    int x = pos.x + dirs[i], y = pos.y + dirs[i + 1];
                    if (x >= 0 && x < m && y >= 0 && y < n && res[x][y] == -1) {
                        res[x][y] = res[pos.x][pos.y] + 1;
                        queue.offer(new Position(x, y));
                    }
                }
            }
            return res;
        }
    }
    
    

    
    

    543. 二叉树的直径

    English Version

    题目描述

    给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

     

    示例 :
    给定二叉树

              1
             / \
            2   3
           / \     
          4   5    
    

    返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

     

    注意:两结点之间的路径长度是以它们之间边的数目表示。

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        int ans = 1;
    
        public int diameterOfBinaryTree(TreeNode root) {
            depth(root);
            return ans - 1;
        }
    
        public int depth(TreeNode node) {
            if (node == null) return 0;
            int L = depth(node.left);
            int R = depth(node.right);
            ans = Math.max(ans, L + R + 1);
            return Math.max(L, R) + 1;
        }
    }
    

    
    

    554. 砖墙

    English Version

    题目描述

    你的面前有一堵方形的、由多行砖块组成的砖墙。 这些砖块高度相同但是宽度不同。你现在要画一条自顶向下的、穿过最少砖块的垂线。

    砖墙由行的列表表示。 每一行都是一个代表从左至右每块砖的宽度的整数列表。

    如果你画的线只是从砖块的边缘经过,就不算穿过这块砖。你需要找出怎样画才能使这条线穿过的砖块数量最少,并且返回穿过的砖块数量。

    你不能沿着墙的两个垂直边缘之一画线,这样显然是没有穿过一块砖的。

     

    示例:

    输入: [[1,2,2,1],
    
          [3,1,2],
    
          [1,3,2],
    
          [2,4],
    
          [3,1,2],
    
          [1,3,1,1]]
    
    
    
    输出: 2
    
    
    
    解释: 
    
    

    在这里插入图片描述

     

    提示:

    1. 每一行砖块的宽度之和应该相等,并且不能超过 INT_MAX。
    2. 每一行砖块的数量在 [1,10,000] 范围内, 墙的高度在 [1,10,000] 范围内, 总的砖块数量不超过 20,000。

    解法

    Python3

    
    

    Java

    class Solution {
        public int leastBricks(List<List<Integer>> wall) {
            Map<Integer, Integer> map = new HashMap<>();
            for (List<Integer> list : wall) {
                int s = 0;
                for (int i = 0; i < list.size() - 1; ++i) {
                    s += list.get(i);
                    map.put(s, map.getOrDefault(s, 0) + 1);
                }
            }
            int max = map.values().stream().max(Integer::compare).orElse(0);
            return wall.size() - max;
        }
    }
    
    

    
    

    556. 下一个更大元素 III

    English Version

    题目描述

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

    示例 1:

    输入: 12
    输出: 21
    

    示例 2:

    输入: 21
    输出: -1
    

    解法

    Python3

    
    

    Java

    class Solution {
        public int nextGreaterElement(int n) {
            if (n < 12) {
                return -1;
            }
            char[] cs = String.valueOf(n).toCharArray();
            int i = cs.length - 2;
            while (i >= 0 && cs[i] >= cs[i + 1]) {
                --i;
            }
            if (i < 0) {
                return -1;
            }
            int j = cs.length - 1;
            while (cs[i] >= cs[j]) {
                --j;
            }
            swap(cs, i, j);
            reverse(cs, i + 1, cs.length - 1);
            long res = 0;
            for (char c : cs) {
                res = res * 10 + c - '0';
            }
            return res <= Integer.MAX_VALUE ? (int) res : -1;
        }
    
        private void reverse(char[] cs, int i, int j) {
            while (i < j) {
                swap(cs, i++, j--);
            }
        }
    
        private void swap(char[] cs, int i, int j) {
            char tmp = cs[i];
            cs[i] = cs[j];
            cs[j] = tmp;
        }
    }
    
    

    
    

    557. 反转字符串中的单词 III

    English Version

    题目描述

    给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

    示例 1:

    输入: "Let's take LeetCode contest"
    输出: "s'teL ekat edoCteeL tsetnoc" 
    

    注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

    解法

    Python3

    
    

    Java

    class Solution {
        public String reverseWords(String s) {
            String flag = " ";
            StringBuilder result = new StringBuilder();
            for (String temp : s.split(flag)) {
                for (int i = temp.length() - 1; i >= 0; i--) {
                    result.append(temp.charAt(i));
                }
                result.append(flag);
            }
            return result.toString().substring(0, s.length());
        }
    }
    

    
    

    560. 和为 K 的子数组

    English Version

    题目描述

    给定一个整数数组和一个整数 k,你需要找到该数组中和为 的连续的子数组的个数。

    示例 1 :

    输入:nums = [1,1,1], k = 2
    输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
    

    说明 :

    1. 数组的长度为 [1, 20,000]。
    2. 数组中元素的范围是 [-1000, 1000] ,且整数 的范围是 [-1e7, 1e7]。

    解法

    Python3

    
    

    Java

    class Solution {
        public int subarraySum(int[] nums, int k) {
            Map<Integer, Integer> map = new HashMap<>();
            map.put(0, 1);
            int res = 0;
            int s = 0;
            for (int i = 0; i < nums.length; ++i) {
                s += nums[i];
                res += map.getOrDefault(s - k, 0);
                map.put(s, map.getOrDefault(s, 0) + 1);
            }
            return res;
        }
    }
    
    

    
    

    561. 数组拆分 I

    English Version

    题目描述

    给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从1 到 n 的 min(ai, bi) 总和最大。

    示例 1:

    输入: [1,4,3,2]
    
    输出: 4
    解释: n 等于 2, 最大总和为 4 = min(1, 2) + min(3, 4).
    

    提示:

    1. n 是正整数,范围在 [1, 10000].
    2. 数组中的元素范围在 [-10000, 10000].

    解法

    先排序,然后求相邻的两个元素的最小值,得到的总和即为结果。

    Python3

    class Solution:
        def arrayPairSum(self, nums: List[int]) -> int:
            return sum(sorted(nums)[::2])
    

    Java

    class Solution {
        public int arrayPairSum(int[] nums) {
            Arrays.sort(nums);
            int res = 0;
            for (int i = 0, n = nums.length; i < n; i += 2) {
                res += nums[i];
            }
            return res;
        }
    }
    

    JavaScript

    /**
     * @param {number[]} nums
     * @return {number}
     */
    var arrayPairSum = function (nums) {
      nums.sort((a, b) => a - b);
      let res = 0;
      for (let i = 0, n = nums.length; i < n; i += 2) {
        res += nums[i];
      }
      return res;
    };
    

    
    

    563. 二叉树的坡度

    English Version

    题目描述

    给定一个二叉树,计算整个树的坡度。

    一个树的节点的坡度定义即为,该节点左子树的结点之和和右子树结点之和的差的绝对值。空结点的的坡度是0。

    整个树的坡度就是其所有节点的坡度之和。

    示例:

    输入: 
             1
           /   \
          2     3
    输出: 1
    解释: 
    结点的坡度 2 : 0
    结点的坡度 3 : 0
    结点的坡度 1 : |2-3| = 1
    树的坡度 : 0 + 0 + 1 = 1
    

    注意:

    1. 任何子树的结点的和不会超过32位整数的范围。
    2. 坡度的值不会超过32位整数的范围。

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
    
        int sum = 0;
    
        public int findTilt(TreeNode root) {
            traverse(root);
            return sum;
        }
    
        public int traverse(TreeNode root) {
            if (root == null) return 0;
            int left = traverse(root.left);
            int right = traverse(root.right);
            sum += Math.abs(left - right);
            return left + right + root.val;
        }
    }
    

    
    

    566. 重塑矩阵

    English Version

    题目描述

    在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。

    给出一个由二维数组表示的矩阵,以及两个正整数rc,分别表示想要的重构的矩阵的行数和列数。

    重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。

    如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

    示例 1:

    输入: 
    nums = 
    [[1,2],
     [3,4]]
    r = 1, c = 4
    输出: 
    [[1,2,3,4]]
    解释:
    行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。
    

    示例 2:

    输入: 
    nums = 
    [[1,2],
     [3,4]]
    r = 2, c = 4
    输出: 
    [[1,2],
     [3,4]]
    解释:
    没有办法将 2 * 2 矩阵转化为 2 * 4 矩阵。 所以输出原矩阵。
    

    注意:

    1. 给定矩阵的宽和高范围在 [1, 100]。
    2. 给定的 r 和 c 都是正数。

    解法

    Python3

    class Solution:
        def matrixReshape(self, nums: List[List[int]], r: int, c: int) -> List[List[int]]:
            m, n = len(nums), len(nums[0])
            if m * n != r * c:
                return nums
            res = [[0] * c for _ in range(r)]
            for x in range(m * n):
                res[x // c][x % c] = nums[x // n][x % n]
            return res
    

    Java

    class Solution {
        public int[][] matrixReshape(int[][] nums, int r, int c) {
            int m = nums.length, n = nums[0].length;
            if (m * n != r * c) return nums;
            int[][] res = new int[r][c];
            for (int i = 0; i < m * n; ++i) {
                res[i / c][i % c] = nums[i / n][i % n];
            }
            return res;
        }
    }
    

    
    

    572. 另一个树的子树

    English Version

    题目描述

    给定两个非空二叉树 st,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。

    示例 1:
    给定的树 s:

         3
        / \
       4   5
      / \
     1   2
    

    给定的树 t:

       4 
      / \
     1   2
    

    返回 true,因为 t 与 s 的一个子树拥有相同的结构和节点值。

    示例 2:
    给定的树 s:

         3
        / \
       4   5
      / \
     1   2
        /
       0
    

    给定的树 t:

       4
      / \
     1   2
    

    返回 false

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public boolean isSubtree(TreeNode s, TreeNode t) {
    
            if (t == null) return true;
            if (s == null) return false;
    
            if (s.val != t.val){
                return isSubtree(s.left, t) || isSubtree(s.right, t);
            }
            return isSameTree(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t);
        }
    
        private boolean isSameTree(TreeNode root1, TreeNode root2){
            if(root1 == null && root2 == null) return true;
            if(root1 == null || root2 == null) return false;
    
            if(root1.val != root2.val) return false;
            return isSameTree(root1.left, root2.left) && isSameTree(root1.right, root2.right);
        }
    }
    

    
    

    576. 出界的路径数

    English Version

    题目描述

    给定一个 m × n 的网格和一个球。球的起始坐标为 (i,j) ,你可以将球移到相邻的单元格内,或者往上、下、左、右四个方向上移动使球穿过网格边界。但是,你最多可以移动 次。找出可以将球移出边界的路径数量。答案可能非常大,返回 结果 mod 109 + 7 的值。

     

    示例 1:

    输入: m = 2, n = 2, N = 2, i = 0, j = 0
    
    输出: 6
    
    解释:
    
    

    在这里插入图片描述

    示例 2:

    输入: m = 1, n = 3, N = 3, i = 0, j = 1
    
    输出: 12
    
    解释:
    
    

    在这里插入图片描述

     

    说明:

    1. 球一旦出界,就不能再被移动回网格内。
    2. 网格的长度和高度在 [1,50] 的范围内。
    3. N 在 [0,50] 的范围内。

    解法

    Python3

    
    

    Java

    class Solution {
        public int findPaths(int m, int n, int N, int i, int j) {
            final int MOD = (int) (1e9 + 7);
            final int[] dirs = new int[]{-1, 0, 1, 0, -1};
            int[][] f = new int[m][n];
            f[i][j] = 1;
            int res = 0;
            for (int step = 0; step < N; ++step) {
                int[][] temp = new int[m][n];
                for (int x = 0; x < m; ++x) {
                    for (int y = 0; y < n; ++y) {
                        for (int k = 0; k < 4; ++k) {
                            int tx = x + dirs[k], ty = y + dirs[k + 1];
                            if (tx >= 0 && tx < m && ty >= 0 && ty < n) {
                                temp[tx][ty] += f[x][y];
                                temp[tx][ty] %= MOD;
                            } else {
                                res += f[x][y];
                                res %= MOD;
                            }
                        }
                    }
                }
                f = temp;
            }
            return res;
        }
    }
    
    

    
    

    581. 最短无序连续子数组

    English Version

    题目描述

    给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。

    你找到的子数组应是最短的,请输出它的长度。

    示例 1:

    输入: [2, 6, 4, 8, 10, 9, 15]
    输出: 5
    解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
    

    说明 :

    1. 输入的数组长度范围在 [1, 10,000]。
    2. 输入的数组可能包含重复元素 ,所以升序的意思是<=。

    解法

    Python3

    
    

    Java

    class Solution {
        public int findUnsortedSubarray(int[] nums) {
            int n = nums.length;
            if (n == 1) {
                return 0;
            }
            int[] res = new int[n];
            for (int i = 0; i < n; ++i) {
                res[i] = nums[i];
            }
            Arrays.sort(res);
            int p = 0;
            for (; p < n; ++p) {
                if (res[p] != nums[p]) {
                    break;
                }
            }
            int q = n - 1;
            for (; q >= 0; --q) {
                if (res[q] != nums[q]) {
                    break;
                }
            }
            return p == n ? 0 : q - p + 1 ;
            
        }
    }
    

    
    

    589. N 叉树的前序遍历

    English Version

    题目描述

    给定一个 N 叉树,返回其节点值的前序遍历

    例如,给定一个 3叉树 :

     

    在这里插入图片描述

     

    返回其前序遍历: [1,3,5,6,2,4]

     

    说明: 递归法很简单,你可以使用迭代法完成此题吗?

    解法

    Python3

    
    

    Java

    class Solution {
        public List<Integer> preorder(Node root) {
            List<Integer> res = new ArrayList<>();
            if (root == null) {
                return res;
            }
            Deque<Node> stack = new ArrayDeque<>();
            stack.push(root);
            while (!stack.isEmpty()) {
                Node node = stack.pop();
                res.add(node.val);
                List<Node> children = node.children;
                for (int i = children.size() - 1; i >= 0; --i) {
                    stack.push(children.get(i));
                }
            }
            return res;
        }
    }
    
    

    
    

    590. N 叉树的后序遍历

    English Version

    题目描述

    给定一个 N 叉树,返回其节点值的后序遍历

    例如,给定一个 3叉树 :

     

    在这里插入图片描述

     

    返回其后序遍历: [5,6,3,2,4,1].

     

    说明: 递归法很简单,你可以使用迭代法完成此题吗?

    解法

    Python3

    
    

    Java

    class Solution {
        public List<Integer> postorder(Node root) {
            List<Integer> res = new ArrayList<>();
            if (root == null) {
                return res;
            }
            Deque<Node> stack = new ArrayDeque<>();
            stack.push(root);
            while (!stack.isEmpty()) {
                Node node = stack.pop();
                res.add(0, node.val);
                for (Node child : node.children) {
                    stack.push(child);
                }
            }
            return res;
        }
    }
    
    

    
    

    605. 种花问题

    English Version

    题目描述

    假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

    给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 。能否在不打破种植规则的情况下种入 朵花?能则返回True,不能则返回False。

    示例 1:

    输入: flowerbed = [1,0,0,0,1], n = 1
    输出: True
    

    示例 2:

    输入: flowerbed = [1,0,0,0,1], n = 2
    输出: False
    

    注意:

    1. 数组内已种好的花不会违反种植规则。
    2. 输入的数组长度范围为 [1, 20000]。
    3. n 是非负整数,且不会超过输入数组的大小。

    解法

    Python3

    
    

    Java

    class Solution {
        public boolean canPlaceFlowers(int[] flowerbed, int n) {
            int len = flowerbed.length;
            int cnt = 0;
            for (int i = 0; i < len; ++i) {
                if (flowerbed[i] == 0 && (i == 0 || flowerbed[i - 1] == 0) && (i == len - 1 || flowerbed[i + 1] == 0)) {
                    ++cnt;
                    flowerbed[i] = 1;
                }
            }
            return cnt >= n;
        }
    }
    

    
    

    606. 根据二叉树创建字符串

    English Version

    题目描述

    你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串。

    空节点则用一对空括号 "()" 表示。而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

    示例 1:

    输入: 二叉树: [1,2,3,4]
           1
         /   \
        2     3
       /    
      4     
    
    输出: "1(2(4))(3)"
    
    解释: 原本将是“1(2(4)())(3())”,
    在你省略所有不必要的空括号对之后,
    它将是“1(2(4))(3)”。
    

    示例 2:

    输入: 二叉树: [1,2,3,null,4]
           1
         /   \
        2     3
         \  
          4 
    
    输出: "1(2()(4))(3)"
    
    解释: 和第一个示例相似,
    除了我们不能省略第一个对括号来中断输入和输出之间的一对一映射关系。
    

    解法

    Python3

    
    

    Java

    class Solution {
        public String tree2str(TreeNode t) {
            if (t == null) {
                return "";
            }
            if (t.right != null) {
                return t.val + "(" + tree2str(t.left) + ")" + "(" + tree2str(t.right) + ")";
            }
            if (t.left != null) {
                return t.val + "(" + tree2str(t.left) + ")";
            }
            return t.val + "";
        }
    }
    
    

    
    

    611. 有效三角形的个数

    English Version

    题目描述

    给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数。

    示例 1:

    输入: [2,2,3,4]
    输出: 3
    解释:
    有效的组合是: 
    2,3,4 (使用第一个 2)
    2,3,4 (使用第二个 2)
    2,2,3
    

    注意:

    1. 数组长度不超过1000。
    2. 数组里整数的范围为 [0, 1000]。

    解法

    Python3

    
    

    Java

    class Solution {
        public int triangleNumber(int[] nums) {
            Arrays.sort(nums);
            int n = nums.length;
            int res = 0;
            for (int i = n - 1; i >= 2; --i) {
                int l = 0, r = i - 1;
                while (l < r) {
                    if (nums[l] + nums[r] > nums[i]) {
                        res += r - l;
                        --r;
                    } else {
                        ++l;
                    }
                }
            }
            return res;
        }
    }
    
    

    
    

    617. 合并二叉树

    English Version

    题目描述

    给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。

    你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

    示例 1:

    输入: 
    	Tree 1                     Tree 2                  
              1                         2                             
             / \                       / \                            
            3   2                     1   3                        
           /                           \   \                      
          5                             4   7                  
    输出: 
    合并后的树:
    	     3
    	    / \
    	   4   5
    	  / \   \ 
    	 5   4   7
    

    注意: 合并必须从两个树的根节点开始。

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
            if (t1 == null) return t2;
            if (t2 == null) return t1;
    
            t1.val = t1.val + t2.val;
            t1.left = mergeTrees(t1.left, t2.left);
            t1.right = mergeTrees(t1.right, t2.right);
            return t1;
        }
    }
    

    Go

    /**
     * Definition for a binary tree node.
     * type TreeNode struct {
     *     Val int
     *     Left *TreeNode
     *     Right *TreeNode
     * }
     */
    func mergeTrees(t1 *TreeNode, t2 *TreeNode) *TreeNode {
        if t1 == nil {
            return t2
        }
        if t2 == nil {
            return t1
        }
        t1.Val += t2.Val
        t1.Left = mergeTrees(t1.Left, t2.Left)
        t1.Right = mergeTrees(t1.Right, t2.Right)
        return t1
    }
    
    
    

    622. 设计循环队列

    English Version

    题目描述

    设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

    循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

    你的实现应该支持如下操作:

    • MyCircularQueue(k): 构造器,设置队列长度为 k 。
    • Front: 从队首获取元素。如果队列为空,返回 -1 。
    • Rear: 获取队尾元素。如果队列为空,返回 -1 。
    • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
    • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
    • isEmpty(): 检查循环队列是否为空。
    • isFull(): 检查循环队列是否已满。

     

    示例:

    MyCircularQueue circularQueue = new MycircularQueue(3); // 设置长度为 3
    
    circularQueue.enQueue(1);  // 返回 true
    
    circularQueue.enQueue(2);  // 返回 true
    
    circularQueue.enQueue(3);  // 返回 true
    
    circularQueue.enQueue(4);  // 返回 false,队列已满
    
    circularQueue.Rear();  // 返回 3
    
    circularQueue.isFull();  // 返回 true
    
    circularQueue.deQueue();  // 返回 true
    
    circularQueue.enQueue(4);  // 返回 true
    
    circularQueue.Rear();  // 返回 4
     

     

    提示:

    • 所有的值都在 0 至 1000 的范围内;
    • 操作数将在 1 至 1000 的范围内;
    • 请不要使用内置的队列库。

    解法

    Python3

    
    

    Java

    class MyCircularQueue {
    
     private Integer[] nums;
        private int head;
        private int tail;
        private int size;
    
        /** Initialize your data structure here. Set the size of the queue to be k. */
        public MyCircularQueue(int k) {
            this.nums = new Integer[k];
            this.head = -1;
            this.tail = -1;
            this.size = 0;
        }
    
        /** Insert an element into the circular queue. Return true if the operation is successful. */
        public boolean enQueue(int value) {
            if (isFull()) {
                return false;
            } else if(this.head == this.tail && this.tail == -1){
                this.head++;
                this.tail++;
                nums[this.tail] = value;
            } else {
                this.tail = (this.tail + 1) % nums.length;
                this.nums[this.tail] = value;
            }
            this.size++;
            return true;
        }
    
        /** Delete an element from the circular queue. Return true if the operation is successful. */
        public boolean deQueue() {
            if (isEmpty()) {
                return false;
            } else if (this.head == this.tail) {
                this.head = -1;
                this.tail = -1;
            } else {
                this.head = (this.head + 1) % this.nums.length;
            }
            this.size--;
            return true;
        }
    
        /** Get the front item from the queue. */
        public int Front() {
            if (isEmpty()) {
                return -1;
            } else {
                return this.nums[this.head];
            }
        }
    
        /** Get the last item from the queue. */
        public int Rear() {
            if (isEmpty()) {
                return -1;
            } else {
                return this.nums[this.tail];
            }
        }
    
        /** Checks whether the circular queue is empty or not. */
        public boolean isEmpty() {
            if (this.size == 0) {
                return true;
            } else {
                return false;
            }
        }
    
        /** Checks whether the circular queue is full or not. */
        public boolean isFull() {
            if (this.size == this.nums.length) {
                return true;
            } else {
                return false;
            }
        }
    }
    
    /**
     * Your MyCircularQueue object will be instantiated and called as such:
     * MyCircularQueue obj = new MyCircularQueue(k);
     * boolean param_1 = obj.enQueue(value);
     * boolean param_2 = obj.deQueue();
     * int param_3 = obj.Front();
     * int param_4 = obj.Rear();
     * boolean param_5 = obj.isEmpty();
     * boolean param_6 = obj.isFull();
     */
    
    

    
    

    633. 平方数之和

    English Version

    题目描述

    给定一个非负整数 c ,你要判断是否存在两个整数 ab,使得 a2 + b2 = c。

    示例1:

    输入: 5
    输出: True
    解释: 1 * 1 + 2 * 2 = 5
    

     

    示例2:

    输入: 3
    输出: False
    

    解法

    Python3

    
    

    Java

    class Solution {
        public boolean judgeSquareSum(int c) {
            int i = 0, j = (int) Math.sqrt(c);
            while (i <= j) {
                int s = i * i + j * j;
                if (s < c) {
                    ++i;
                } else if (s > c) {
                    --j;
                } else {
                    return true;
                }
            }
            return false;
        }
    }
    
    

    
    

    637. 二叉树的层平均值

    English Version

    题目描述

    给定一个非空二叉树, 返回一个由每层节点平均值组成的数组.

    示例 1:

    输入:
        3
       / \
      9  20
        /  \
       15   7
    输出: [3, 14.5, 11]
    解释:
    第0层的平均值是 3,  第1层是 14.5, 第2层是 11. 因此返回 [3, 14.5, 11].
    

    注意:

    1. 节点值的范围在32位有符号整数范围内。

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
    
        public List<Double> averageOfLevels(TreeNode root) {
            if (root == null) return null;
    
            List<Double> res = new ArrayList<>();
            LinkedList<TreeNode> queue = new LinkedList<>();
            queue.offer(root);
    
            while (!queue.isEmpty()) {
                double sum = 0, size = queue.size();
                for (int i = 0; i < size; i ++) {
                    TreeNode node = queue.poll();
                    sum += node.val;
                    if (node.left != null) {
                        queue.offer(node.left);
                    }
                    if (node.right != null) {
                        queue.offer(node.right);
                    }
                }
                res.add(sum / size);
            }
            return res;
        }
    }
    

    
    

    645. 错误的集合

    English Version

    题目描述

    集合 S 包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复。

    给定一个数组 nums 代表了集合 S 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

    示例 1:

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

    注意:

    1. 给定数组的长度范围是 [2, 10000]。
    2. 给定的数组是无序的。

    解法

    首先使用 1 到 n 的所有数字做异或运算,然后再与数组中的所有数字异或,得到的值就是缺失数字与重复的数字异或的结果。

    接着计算中这个值中其中一个非零的位 pos。然后 pos 位是否为 1,将 nums 数组的元素分成两部分,分别异或;接着将 1~n 的元素也分成两部分,分别异或。得到的两部分结果分别为 a,b,即是缺失数字与重复数字。

    最后判断数组中是否存在 a 或 b,若存在 a,说明重复数字是 a,返回 [a,b],否则返回 [b,a]

    Python3

    class Solution:
        def findErrorNums(self, nums: List[int]) -> List[int]:
            res = 0
            for num in nums:
                res ^= num
            for i in range(1, len(nums) + 1):
                res ^= i
            pos = 0
            while (res & 1) == 0:
                res >>= 1
                pos += 1
            a = b = 0
            for num in nums:
                if ((num >> pos) & 1) == 0:
                    a ^= num
                else:
                    b ^= num
            for i in range(1, len(nums) + 1):
                if ((i >> pos) & 1) == 0:
                    a ^= i
                else:
                    b ^= i
            for num in nums:
                if num == a:
                    return [a, b]
            return [b, a]
    

    Java

    class Solution {
        public int[] findErrorNums(int[] nums) {
            int res = 0;
            for (int num : nums) {
                res ^= num;
            }
            for (int i = 1, n = nums.length; i < n + 1; ++i) {
                res ^= i;
            }
            int pos = 0;
            while ((res & 1) == 0) {
                res >>= 1;
                ++pos;
            }
            int a = 0, b = 0;
            for (int num : nums) {
                if (((num >> pos) & 1) == 0) {
                    a ^= num;
                } else {
                    b ^= num;
                }
            }
            for (int i = 1, n = nums.length; i < n + 1; ++i) {
                if (((i >> pos) & 1) == 0) {
                    a ^= i;
                } else {
                    b ^= i;
                }
            }
            for (int num : nums) {
                if (num == a) {
                    return new int[]{a, b};
                }
            }
            return new int[]{b, a};
        }
    }
    

    
    

    650. 只有两个键的键盘

    English Version

    题目描述

    最初在一个记事本上只有一个字符 'A'。你每次可以对这个记事本进行两种操作:

    1. Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。
    2. Paste (粘贴) : 你可以粘贴你上一次复制的字符。

    给定一个数字 n 。你需要使用最少的操作次数,在记事本中打印出恰好 n 个 'A'。输出能够打印出 n 个 'A' 的最少操作次数。

    示例 1:

    输入: 3
    输出: 3
    解释:
    最初, 我们只有一个字符 'A'。
    第 1 步, 我们使用 Copy All 操作。
    第 2 步, 我们使用 Paste 操作来获得 'AA'。
    第 3 步, 我们使用 Paste 操作来获得 'AAA'。
    

    说明:

    1. n 的取值范围是 [1, 1000] 。

    解法

    Python3

    
    

    Java

    class Solution {
        public int minSteps(int n) {
            int res = 0;
            for (int i = 2; n > 1; ++i) {
                while (n % i == 0) {
                    res += i;
                    n /= i;
                }
            }
            return res;
        }
    }
    
    

    
    

    652. 寻找重复的子树

    English Version

    题目描述

    给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。

    两棵树重复是指它们具有相同的结构以及相同的结点值。

    示例 1:

            1
           / \
          2   3
         /   / \
        4   2   4
           /
          4
    

    下面是两个重复的子树:

          2
         /
        4
    

        4
    

    因此,你需要以列表的形式返回上述重复子树的根结点。

    解法

    Python3

    
    

    Java

    class Solution {
        public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
            List<TreeNode> res = new ArrayList<>();
            dfs(root, new HashMap<>(), res);
            return res;
        }
    
        private String dfs(TreeNode root, Map<String, Integer> map, List<TreeNode> res) {
            if (root == null) {
                return "";
            }
            String s = root.val + "_" + dfs(root.left, map, res) + "_" + dfs(root.right, map, res);
            map.put(s, map.getOrDefault(s, 0) + 1);
            if (map.get(s) == 2) {
                res.add(root);
            }
            return s;
        }
    }
    
    

    
    

    664. 奇怪的打印机

    English Version

    题目描述

    有台奇怪的打印机有以下两个特殊要求:

    1. 打印机每次只能打印同一个字符序列。
    2. 每次可以在任意起始和结束位置打印新字符,并且会覆盖掉原来已有的字符。

    给定一个只包含小写英文字母的字符串,你的任务是计算这个打印机打印它需要的最少次数。

    示例 1:

    输入: "aaabbb"
    输出: 2
    解释: 首先打印 "aaa" 然后打印 "bbb"。
    

    示例 2:

    输入: "aba"
    输出: 2
    解释: 首先打印 "aaa" 然后在第二个位置打印 "b" 覆盖掉原来的字符 'a'。

    提示: 输入字符串的长度不会超过 100。

    解法

    Python3

    
    

    Java

    class Solution {
        public int strangePrinter(String s) {
            if (s.isEmpty()) {
                return 0;
            }
            int n = s.length();
            int[][] f = new int[n + 1][n + 1];
            for (int i = 0; i < n; ++i) {
                f[i][i] = 1;
            }
            for (int i = n - 2; i >= 0; --i) {
                for (int j = i + 1; j < n; ++j) {
                    f[i][j] = 1 + f[i + 1][j];
                    for (int k = i + 1; k <= j; ++k) {
                        if (s.charAt(i) == s.charAt(k)) {
                            f[i][j] = Math.min(f[i][j], f[i + 1][k] + f[k + 1][j]);
                        }
                    }
                }
            }
            return f[0][n - 1];
        }
    }
    
    

    
    

    669. 修剪二叉搜索树

    English Version

    题目描述

    给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。

    示例 1:

    输入: 
        1
       / \
      0   2
    
      L = 1
      R = 2
    
    输出: 
        1
          \
           2
    

    示例 2:

    输入: 
        3
       / \
      0   4
       \
        2
       /
      1
    
      L = 1
      R = 3
    
    输出: 
          3
         / 
       2   
      /
     1
    

    解法

    Python3

    
    

    Java

    class Solution {
        public TreeNode trimBST(TreeNode root, int L, int R) {
            if (root == null) return null;
            if (root.val < L) return trimBST(root.right, L, R);
            if (root.val > R) return trimBST(root.left, L, R);
            root.left = trimBST(root.left, L, R);
            root.right = trimBST(root.right, L, R);
            return root;
        }
    }
    
    

    
    

    671. 二叉树中第二小的节点

    English Version

    题目描述

    给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么这个节点的值不大于它的子节点的值。 

    给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1

    示例 1:

    输入: 
        2
       / \
      2   5
         / \
        5   7
    
    输出: 5
    说明: 最小的值是 2 ,第二小的值是 5 。
    

    示例 2:

    输入: 
        2
       / \
      2   2
    
    输出: -1
    说明: 最小的值是 2, 但是不存在第二小的值。
    

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public int findSecondMinimumValue(TreeNode root) {
            if (root == null || root.left == null) return -1;
            int limit = Integer.MAX_VALUE;
            Stack<TreeNode> stack = new Stack<>();
            stack.push(root);
            while (!stack.isEmpty()) {
                TreeNode node = stack.pop();
                if (node.val != root.val) {
                    limit = Math.min(limit, node.val - root.val);
                }
                if (node.left != null) {
                    stack.push(node.left);
                    stack.push(node.right);
                }
            }
            return limit == Integer.MAX_VALUE ? -1 : root.val + limit;
        }
    }
    

    
    

    673. 最长递增子序列的个数

    English Version

    题目描述

    给定一个未排序的整数数组,找到最长递增子序列的个数。

    示例 1:

    输入: [1,3,5,4,7]
    输出: 2
    解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。
    

    示例 2:

    输入: [2,2,2,2,2]
    输出: 5
    解释: 最长递增子序列的长度是1,并且存在5个子序列的长度为1,因此输出5。
    

    注意: 给定的数组长度不超过 2000 并且结果一定是32位有符号整数。

    解法

    Python3

    
    

    Java

    class Solution {
        public int findNumberOfLIS(int[] nums) {
            if (nums == null || nums.length == 0) {
                return 0;
            }
            int n = nums.length;
            int[] dp = new int[n];
            int[] f = new int[n];
            Arrays.fill(dp, 1);
            Arrays.fill(f, 1);
            int max = 0;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < i; ++j) {
                    if (nums[i] > nums[j]) {
                        if (dp[j] + 1 > dp[i]) {
                            dp[i] = dp[j] + 1;
                            f[i] = f[j];
                        } else if (dp[j] + 1 == dp[i]) {
                            f[i] += f[j];
                        }
                    }
                }
                max = Math.max(max, dp[i]);
            }
            int res = 0;
            for (int i = 0; i < n; ++i) {
                if (dp[i] == max) {
                    res += f[i];
                }
            }
            return res;
        }
    }
    
    

    
    

    674. 最长连续递增序列

    English Version

    题目描述

    给定一个未经排序的整数数组,找到最长且连续的的递增序列。

    示例 1:

    输入: [1,3,5,4,7]
    输出: 3
    解释: 最长连续递增序列是 [1,3,5], 长度为3。
    尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开。 
    

    示例 2:

    输入: [2,2,2,2,2]
    输出: 1
    解释: 最长连续递增序列是 [2], 长度为1。
    

    注意:数组长度不会超过10000。

    解法

    设 f(i) 表示将数组第 i 项作为最长连续递增子序列的最后一项时,子序列的长度。

    那么,当 nums[i - 1] < nums[i],即 f(i) = f(i - 1) + 1,否则 f(i) = 1。问题转换为求 f(i) (i ∈ [0 ,n - 1]) 的最大值。

    由于 f(i) 只与前一项 f(i - 1) 有关联,故不需要用一个数组存储。

    Python3

    class Solution:
        def findLengthOfLCIS(self, nums: List[int]) -> int:
            n = len(nums)
            if n < 2:
                return n
            res = f = 1
            for i in range(1, n):
                f = 1 + (f if nums[i - 1] < nums[i] else 0)
                res = max(res, f)
            return res
    

    Java

    class Solution {
        public int findLengthOfLCIS(int[] nums) {
            int n;
            if ((n = nums.length) < 2) return n;
            int res = 1, f = 1;
            for (int i = 1; i < n; ++i) {
                f = 1 + (nums[i - 1] < nums[i] ? f : 0);
                res = Math.max(res, f);
            }
            return res;
        }
    }
    

    
    

    679. 24 点游戏

    English Version

    题目描述

    你有 4 张写有 1 到 9 数字的牌。你需要判断是否能通过 */+-() 的运算得到 24。

    示例 1:

    输入: [4, 1, 8, 7]
    输出: True
    解释: (8-4) * (7-1) = 24
    

    示例 2:

    输入: [1, 2, 1, 2]
    输出: False
    

    注意:

    1. 除法运算符 / 表示实数除法,而不是整数除法。例如 4 / (1 - 2/3) = 12 。
    2. 每个运算符对两个数进行运算。特别是我们不能用 - 作为一元运算符。例如,[1, 1, 1, 1] 作为输入时,表达式 -1 - 1 - 1 - 1 是不允许的。
    3. 你不能将数字连接在一起。例如,输入为 [1, 2, 1, 2] 时,不能写成 12 + 12 。

    解法

    Python3

    
    

    Java

    class Solution {
        public boolean judgePoint24(int[] nums) {
            return dfs(Arrays.stream(nums).boxed().map(Double::new).collect(Collectors.toList()));
        }
    
        private boolean dfs(List<Double> numList) {
            if (numList.size() == 0) {
                return false;
            }
            if (numList.size() == 1) {
                return Math.abs(Math.abs(numList.get(0) - 24.0)) < 0.000001d;
            }
            for (int i = 0; i < numList.size(); i++) {
                for (int j = i + 1; j < numList.size(); j++) {
                    boolean valid = dfs(getList(numList, i, j, 0)) || dfs(getList(numList, i, j, 1))
                            || dfs(getList(numList, i, j, 2)) || dfs(getList(numList, i, j, 3))
                            || dfs(getList(numList, i, j, 4)) || dfs(getList(numList, i, j, 5));
                    if (valid) {
                        return true;
                    }
                }
            }
            return false;
        }
    
        private List<Double> getList(List<Double> numList, int i, int j, int operate) {
            List<Double> candidate = new ArrayList<>();
            for (int k = 0; k < numList.size(); k++) {
                if (k == i || k == j) {
                    continue;
                }
                candidate.add(numList.get(k));
            }
    
            switch (operate) {
                // a + b
                case 0:
                    candidate.add(numList.get(i) + numList.get(j));
                    break;
                // a - b
                case 1:
                    candidate.add(numList.get(i) - numList.get(j));
                    break;
                // b - a
                case 2:
                    candidate.add(numList.get(j) - numList.get(i));
                    break;
                // a * b
                case 3:
                    candidate.add(numList.get(i) * numList.get(j));
                    break;
                // a / b
                case 4:
                    if (numList.get(j) == 0) {
                        return Collections.emptyList();
                    }
                    candidate.add(numList.get(i) / numList.get(j));
                    break;
                // b / a
                case 5:
                    if (numList.get(i) == 0) {
                        return Collections.emptyList();
                    }
                    candidate.add(numList.get(j) / numList.get(i));
                    break;
            }
            return candidate;
        }
    }
    

    
    

    682. 棒球比赛

    English Version

    题目描述

    你现在是棒球比赛记录员。
    给定一个字符串列表,每个字符串可以是以下四种类型之一:
    1.整数(一轮的得分):直接表示您在本轮中获得的积分数。
    2. "+"(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
    3. "D"(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
    4. "C"(一个操作,这不是一个回合的分数):表示您获得的最后一个有效 回合的分数是无效的,应该被移除。

    每一轮的操作都是永久性的,可能会对前一轮和后一轮产生影响。
    你需要返回你在所有回合中得分的总和。

    示例 1:

    输入: ["5","2","C","D","+"]
    输出: 30
    解释: 
    第1轮:你可以得到5分。总和是:5。
    第2轮:你可以得到2分。总和是:7。
    操作1:第2轮的数据无效。总和是:5。
    第3轮:你可以得到10分(第2轮的数据已被删除)。总数是:15。
    第4轮:你可以得到5 + 10 = 15分。总数是:30。
    

    示例 2:

    输入: ["5","-2","4","C","D","9","+","+"]
    输出: 27
    解释: 
    第1轮:你可以得到5分。总和是:5。
    第2轮:你可以得到-2分。总数是:3。
    第3轮:你可以得到4分。总和是:7。
    操作1:第3轮的数据无效。总数是:3。
    第4轮:你可以得到-4分(第三轮的数据已被删除)。总和是:-1。
    第5轮:你可以得到9分。总数是:8。
    第6轮:你可以得到-4 + 9 = 5分。总数是13。
    第7轮:你可以得到9 + 5 = 14分。总数是27。
    

    注意:

    • 输入列表的大小将介于1和1000之间。
    • 列表中的每个整数都将介于-30000和30000之间。

    解法

    栈实现。

    Python3

    class Solution:
        def calPoints(self, ops: List[str]) -> int:
            stack = []
            for op in ops:
                if op == 'C':
                    stack.pop()
                elif op == 'D':
                    stack.append(stack[-1] << 1)
                elif op == '+':
                    stack.append(stack[-1] + stack[-2])
                else:
                    stack.append(int(op))
            return sum(stack)
    

    Java

    class Solution {
        public int calPoints(String[] ops) {
            Deque<Integer> stack = new ArrayDeque<>();
            for (String op : ops) {
                if ("C".equals(op)) {
                    stack.pop();
                } else if ("D".equals(op)) {
                    stack.push(stack.peek() << 1);
                } else if ("+".equals(op)) {
                    Integer a = stack.pop();
                    Integer b = stack.peek();
                    stack.push(a);
                    stack.push(a + b);
                } else {
                    stack.push(Integer.valueOf(op));
                }
            }
            int res = 0;
            for (Integer score : stack) {
                res += score;
            }
            return res;
        }
    }
    

    
    

    684. 冗余连接

    English Version

    题目描述

    在本问题中, 树指的是一个连通且无环的无向图。

    输入一个图,该图由一个有着N个节点 (节点值不重复1, 2, ..., N) 的树及一条附加的边构成。附加的边的两个顶点包含在1到N中间,这条附加的边不属于树中已存在的边。

    结果图是一个以组成的二维数组。每一个的元素是一对[u, v] ,满足 u < v,表示连接顶点u 和v无向图的边。

    返回一条可以删去的边,使得结果图是一个有着N个节点的树。如果有多个答案,则返回二维数组中最后出现的边。答案边 [u, v] 应满足相同的格式 u < v

    示例 1:

    输入: [[1,2], [1,3], [2,3]]
    输出: [2,3]
    解释: 给定的无向图为:
      1
     / \
    2 - 3
    

    示例 2:

    输入: [[1,2], [2,3], [3,4], [1,4], [1,5]]
    输出: [1,4]
    解释: 给定的无向图为:
    5 - 1 - 2
        |   |
        4 - 3
    

    注意:

    • 输入的二维数组大小在 3 到 1000。
    • 二维数组中的整数在1到N之间,其中N是输入数组的大小。

    更新(2017-09-26):
    我们已经重新检查了问题描述及测试用例,明确图是无向 图。对于有向图详见冗余连接II对于造成任何不便,我们深感歉意。

    解法

    Python3

    
    

    Java

    class Solution {
        public int[] findRedundantConnection(int[][] edges) {
            int n = edges.length;
            int[] f = new int[n + 1];
            for (int i = 1; i <= n; ++i) {
                f[i] = i;
            }
            for (int[] edge : edges) {
                int p = find(edge[0], f);
                int q = find(edge[1], f);
                if (p == q) {
                    return edge;
                }
                f[p] = q;
            }
            return null;
        }
    
        private int find(int x, int[] f) {
            if (f[x] != x) {
                f[x] = find(f[x], f);
            }
            return f[x];
        }
    }
    
    

    
    

    687. 最长同值路径

    English Version

    题目描述

    给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。

    注意:两个节点之间的路径长度由它们之间的边数表示。

    示例 1:

    输入:

                  5
                 / \
                4   5
               / \   \
              1   1   5
    

    输出:

    2
    

    示例 2:

    输入:

                  1
                 / \
                4   5
               / \   \
              4   4   5
    

    输出:

    2
    

    注意: 给定的二叉树不超过10000个结点。 树的高度不超过1000。

    解法

    Python3

    
    

    Java

    class Solution {
        public int longestUnivaluePath(TreeNode root) {
            int[] res = new int[1];
            dfs(root, res);
            return res[0];
        }
    
        private int dfs(TreeNode root, int[] res) {
            if (root == null) {
                return 0;
            }
            int left = dfs(root.left, res);
            int right = dfs(root.right, res);
            left = root.left != null && root.left.val == root.val ? left + 1 : 0;
            right = root.right != null && root.right.val == root.val ? right + 1 : 0;
            res[0] = Math.max(res[0], left + right);
            return Math.max(left, right);
        }
    }
    
    

    
    

    690. 员工的重要性

    English Version

    题目描述

    给定一个保存员工信息的数据结构,它包含了员工唯一的id重要度 直系下属的id

    比如,员工1是员工2的领导,员工2是员工3的领导。他们相应的重要度为15, 10, 5。那么员工1的数据结构是[1, 15, [2]],员工2的数据结构是[2, 10, [3]],员工3的数据结构是[3, 5, []]。注意虽然员工3也是员工1的一个下属,但是由于并不是直系下属,因此没有体现在员工1的数据结构中。

    现在输入一个公司的所有员工信息,以及单个员工id,返回这个员工和他所有下属的重要度之和。

    示例 1:

    输入: [[1, 5, [2, 3]], [2, 3, []], [3, 3, []]], 1
    输出: 11
    解释:
    员工1自身的重要度是5,他有两个直系下属2和3,而且2和3的重要度均为3。因此员工1的总重要度是 5 + 3 + 3 = 11。
    

    注意:

    1. 一个员工最多有一个直系领导,但是可以有多个直系下属
    2. 员工数量不超过2000。

    解法

    Python3

    
    

    Java

    /*
    // Employee info
    class Employee {
        // It's the unique id of each node;
        // unique id of this employee
        public int id;
        // the importance value of this employee
        public int importance;
        // the id of direct subordinates
        public List<Integer> subordinates;
    };
    */
    
    import java.util.*;
    
    class Solution {
    	public int getImportance(List<Employee> employees, int id) {
    		Map<Integer, Employee> map = new HashMap<>();
    		for (Employee employee : employees) {
    			map.put(employee.id, employee);
    		}
    		return dfs(map, id);
    	}
    
    	private int dfs(Map<Integer, Employee> map, int id) {
    		Employee employee = map.get(id);
    		int ans = employee.importance;
    		for (Integer subordinate : employee.subordinates) {
    			ans += dfs(map, subordinate);
    		}
    		return ans;
    	}
    }
    

    
    

    695. 岛屿的最大面积

    English Version

    题目描述

    给定一个包含了一些 01 的非空二维数组 grid

    一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

    找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)

     

    示例 1:

    [[0,0,1,0,0,0,0,1,0,0,0,0,0],
     [0,0,0,0,0,0,0,1,1,1,0,0,0],
     [0,1,1,0,1,0,0,0,0,0,0,0,0],
     [0,1,0,0,1,1,0,0,1,0,1,0,0],
     [0,1,0,0,1,1,0,0,1,1,1,0,0],
     [0,0,0,0,0,0,0,0,0,0,1,0,0],
     [0,0,0,0,0,0,0,1,1,1,0,0,0],
     [0,0,0,0,0,0,0,1,1,0,0,0,0]]
    

    对于上面这个给定矩阵应返回 6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1

    示例 2:

    [[0,0,0,0,0,0,0,0]]

    对于上面这个给定的矩阵, 返回 0

     

    注意: 给定的矩阵grid 的长度和宽度都不超过 50。

    解法

    Python3

    
    

    Java

    class Solution {
        public int maxAreaOfIsland(int[][] grid) {
            int res = 0;
            int m = grid.length;
            int n = grid[0].length;
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    res = Math.max(res, dfs(grid, i, j, m, n));
                }
            }
            return res;
        }
        
        private int dfs(int[][] grid, int i, int j, int m, int n) {
            if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] == 0) {
                return 0;
            }
            grid[i][j] = 0;
            return 1 
                + dfs(grid, i - 1, j, m, n)
                + dfs(grid, i + 1, j, m, n)
                + dfs(grid, i, j - 1, m, n)
                + dfs(grid, i, j + 1, m, n);
        }
    }
    

    
    

    696. 计数二进制子串

    English Version

    题目描述

    给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。

    重复出现的子串要计算它们出现的次数。

    示例 1 :

    输入: "00110011"
    输出: 6
    解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。
    
    请注意,一些重复出现的子串要计算它们出现的次数。
    
    另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。
    

    示例 2 :

    输入: "10101"
    输出: 4
    解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。
    

    注意:

    • s.length 在1到50,000之间。
    • s 只包含“0”或“1”字符。

    解法

    Python3

    
    

    Java

    class Solution {
        public int countBinarySubstrings(String s) {
    		     int[] group = new int[s.length()];
    		     int k = 0;
    		     Arrays.fill(group , 0);
    		     group[0] = 1;
    		     for(int i = 1;i < s.length();i++) {
    		    	   if(s.charAt(i) == s.charAt(i-1))
    		    		   group[k]++;
    		    	   else
    		    		   group[++k] = 1;
    		     }
    		     int ans = 0;
    		     for(int i = 1;i < s.length() && group[i] != 0;i++) {
    		    	   ans += Math.min(group[i-1], group[i]);
    		     }
    		     return ans;
        }
    }
    
    

    
    

    697. 数组的度

    English Version

    题目描述

    给定一个非空且只包含非负数的整数数组 nums, 数组的度的定义是指数组里任一元素出现频数的最大值。

    你的任务是找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。

    示例 1:

    输入: [1, 2, 2, 3, 1]
    输出: 2
    解释: 
    输入数组的度是2,因为元素1和2的出现频数最大,均为2.
    连续子数组里面拥有相同度的有如下所示:
    [1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
    最短连续子数组[2, 2]的长度为2,所以返回2.
    

    示例 2:

    输入: [1,2,2,3,1,4,2]
    输出: 6
    

    注意:

    • nums.length 在1到50,000区间范围内。
    • nums[i] 是一个在0到49,999范围内的整数。

    解法

    遍历数组,用哈希表记录数组每个元素出现的次数,以及首次、末次出现的位置。然后遍历哈希表,获取元素出现次数最多(可能有多个)且首末位置差最小的数。

    Python3

    class Solution:
        def findShortestSubArray(self, nums: List[int]) -> int:
            mapper = {}
            for i, v in enumerate(nums):
                if v in mapper:
                    arr = mapper[v]
                    arr[0] += 1
                    arr[2] = i
                else:
                    arr = [1, i, i]
                    mapper[v] = arr
            max_degree = min_len = 0
            for arr in mapper.values():
                if max_degree < arr[0]:
                    max_degree = arr[0]
                    min_len = arr[2] - arr[1] + 1
                elif max_degree == arr[0]:
                    min_len = min(min_len, arr[2] - arr[1] + 1)
            return min_len
    

    Java

    class Solution {
        public int findShortestSubArray(int[] nums) {
            Map<Integer, int[]> mapper = new HashMap<>();
            for (int i = 0, n = nums.length; i < n; ++i) {
                if (mapper.containsKey(nums[i])) {
                    int[] arr = mapper.get(nums[i]);
                    ++arr[0];
                    arr[2] = i;
                } else {
                    int[] arr = new int[]{1, i, i};
                    mapper.put(nums[i], arr);
                }
            }
    
            int maxDegree = 0, minLen = 0;
            for (Map.Entry<Integer, int[]> entry : mapper.entrySet()) {
                int[] arr = entry.getValue();
                if (maxDegree < arr[0]) {
                    maxDegree = arr[0];
                    minLen = arr[2] - arr[1] + 1;
                } else if (maxDegree == arr[0]) {
                    minLen = Math.min(minLen, arr[2] - arr[1] + 1);
                }
            }
            return minLen;
        }
    }
    

    
    

    700. 二叉搜索树中的搜索

    English Version

    题目描述

    给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。

    例如,

    给定二叉搜索树:
    
            4
           / \
          2   7
         / \
        1   3
    
    和值: 2
    

    你应该返回如下子树:

          2     
         / \   
        1   3
    

    在上述示例中,如果要找的值是 5,但因为没有节点值为 5,我们应该返回 NULL

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode searchBST(TreeNode root, int val) {
            if (root == null) return null;
            if (root.val == val) return root;
            if (root.val < val) return searchBST(root.right, val);
            else return searchBST(root.left, val);
        }
    }
    
    

    
    

    701. 二叉搜索树中的插入操作

    English Version

    题目描述

    给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 保证原始二叉搜索树中不存在新值。

    注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。

    例如, 

    给定二叉搜索树:
    
            4
           / \
          2   7
         / \
        1   3
    
    和 插入的值: 5
    

    你可以返回这个二叉搜索树:

             4
           /   \
          2     7
         / \   /
        1   3 5
    

    或者这个树也是有效的:

             5
           /   \
          2     7
         / \   
        1   3
             \
              4
    

    解法

    Python3

    
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode insertIntoBST(TreeNode root, int val) {
    
            if(root == null){
                root = new TreeNode(val);
          }
    
            if(val < root.val){
                root.left = insertIntoBST(root.left, val);
            }
            else if(val > root.val){
                root.right = insertIntoBST(root.right, val);
            }
    
            // return the unchanged pointer
            return root;
        }
    }
    
    

    
    

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

    English Version

    题目描述

    设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。

    你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用 KthLargest.add,返回当前数据流中第K大的元素。

    示例:

    int k = 3;
    int[] arr = [4,5,8,2];
    KthLargest kthLargest = new KthLargest(3, arr);
    kthLargest.add(3);   // returns 4
    kthLargest.add(5);   // returns 5
    kthLargest.add(10);  // returns 5
    kthLargest.add(9);   // returns 8
    kthLargest.add(4);   // returns 8
    

    说明:
    你可以假设 nums 的长度≥ k-1 且k ≥ 1。

    解法

    Python3

    
    

    Java

    class KthLargest {
    
        private PriorityQueue<Integer> minHeap;
        private int size;
    
        public KthLargest(int k, int[] nums) {
            minHeap = new PriorityQueue<>(k);
            size = k;
            for (int e : nums) {
                add(e);
            }
        }
    
        public int add(int val) {
            if (minHeap.size() < size) {
                minHeap.add(val);
            } else {
                if (minHeap.peek() < val) {
                    minHeap.poll();
                    minHeap.add(val);
                }
            }
            return minHeap.peek();
        }
    }
    
    /**
     * Your KthLargest object will be instantiated and called as such: KthLargest
     * obj = new KthLargest(k, nums); int param_1 = obj.add(val);
     */
    

    
    

    704. 二分查找

    English Version

    题目描述

    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1


    示例 1:

    输入: nums = [-1,0,3,5,9,12], target = 9
    输出: 4
    解释: 9 出现在 nums 中并且下标为 4
    

    示例 2:

    输入: nums = [-1,0,3,5,9,12], target = 2
    输出: -1
    解释: 2 不存在 nums 中因此返回 -1
    

     

    提示:

    1. 你可以假设 nums 中的所有元素是不重复的。
    2. n 将在 [1, 10000]之间。
    3. nums 的每个元素都将在 [-9999, 9999]之间。

    解法

    Python3

    
    

    Java

    class Solution {
        public int search(int[] nums, int target) {
            int l = 0, r = nums.length - 1;
            while (l <= r) {
                int mid = l + r >>> 1;
                if (nums[mid] < target) {
                    l = mid + 1;
                } else if (nums[mid] > target) {
                    r = mid - 1;
                } else {
                    return mid;
                }
            }
            return -1;
        }
    }
    
    

    
    

    707. 设计链表

    English Version

    题目描述

    设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 nextval 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

    在链表类中实现这些功能:

    • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1
    • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
    • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
    • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
    • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

     

    示例:

    MyLinkedList linkedList = new MyLinkedList();
    linkedList.addAtHead(1);
    linkedList.addAtTail(3);
    linkedList.addAtIndex(1,2);   //链表变为1-> 2-> 3
    linkedList.get(1);            //返回2
    linkedList.deleteAtIndex(1);  //现在链表是1-> 3
    linkedList.get(1);            //返回3
    

     

    提示:

    • 所有val值都在 [1, 1000] 之内。
    • 操作次数将在  [1, 1000] 之内。
    • 请不要使用内置的 LinkedList 库。

    解法

    定义虚拟头结点 dummy,count 记录当前链表结点个数。

    Python3

    class ListNode:
    
        def __init__(self, val=0, next=None):
            self.val = val
            self.next = next
    
    
    class MyLinkedList:
    
        def __init__(self):
            """
            Initialize your data structure here.
            """
            self.dummy = ListNode()
            self.count = 0
    
    
        def get(self, index: int) -> int:
            """
            Get the value of the index-th node in the linked list. If the index is invalid, return -1.
            """
            if index < 0 or index >= self.count:
                return -1
            cur = self.dummy.next
            for _ in range(index):
                cur = cur.next
            return cur.val
    
    
        def addAtHead(self, val: int) -> None:
            """
            Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
            """
            self.addAtIndex(0, val)
    
    
        def addAtTail(self, val: int) -> None:
            """
            Append a node of value val to the last element of the linked list.
            """
            self.addAtIndex(self.count, val)
    
    
        def addAtIndex(self, index: int, val: int) -> None:
            """
            Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
            """
            if index > self.count:
                return
            pre = self.dummy
            for _ in range(index):
                pre = pre.next
            pre.next = ListNode(val, pre.next)
            self.count += 1
    
    
        def deleteAtIndex(self, index: int) -> None:
            """
            Delete the index-th node in the linked list, if the index is valid.
            """
            if index < 0 or index >= self.count:
                return
            pre = self.dummy
            for _ in range(index):
                pre = pre.next
            t = pre.next
            pre.next = t.next
            t.next = None
            self.count -= 1
    
    
    
    # Your MyLinkedList object will be instantiated and called as such:
    # obj = MyLinkedList()
    # param_1 = obj.get(index)
    # obj.addAtHead(val)
    # obj.addAtTail(val)
    # obj.addAtIndex(index,val)
    # obj.deleteAtIndex(index)
    

    Java

    class MyLinkedList {
    
        private class ListNode {
            int val;
            ListNode next;
            ListNode(int val) {
                this(val, null);
            }
            ListNode(int val, ListNode next) {
                this.val = val;
                this.next = next;
            }
        }
    
        private ListNode dummy;
        private int count;
    
        /** Initialize your data structure here. */
        public MyLinkedList() {
            dummy = new ListNode(0);
            count = 0;
        }
    
        /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
        public int get(int index) {
            if (index < 0 || index >= count) {
                return -1;
            }
            ListNode cur = dummy.next;
            while (index-- > 0) {
                cur = cur.next;
            }
            return cur.val;
        }
    
        /** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
        public void addAtHead(int val) {
            addAtIndex(0, val);
        }
    
        /** Append a node of value val to the last element of the linked list. */
        public void addAtTail(int val) {
            addAtIndex(count, val);
        }
    
        /** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
        public void addAtIndex(int index, int val) {
            if (index > count) {
                return;
            }
            ListNode pre = dummy;
            while (index-- > 0) {
                pre = pre.next;
            }
            pre.next = new ListNode(val, pre.next);
            ++count;
        }
    
        /** Delete the index-th node in the linked list, if the index is valid. */
        public void deleteAtIndex(int index) {
            if (index < 0 || index >= count) {
                return;
            }
            ListNode pre = dummy;
            while (index-- > 0) {
                pre = pre.next;
            }
            ListNode t = pre.next;
            pre.next = t.next;
            t.next = null;
            --count;
        }
    }
    
    /**
     * Your MyLinkedList object will be instantiated and called as such:
     * MyLinkedList obj = new MyLinkedList();
     * int param_1 = obj.get(index);
     * obj.addAtHead(val);
     * obj.addAtTail(val);
     * obj.addAtIndex(index,val);
     * obj.deleteAtIndex(index);
     */
    

    
    

    718. 最长重复子数组

    English Version

    题目描述

    给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。

    示例 1:

    输入:
    A: [1,2,3,2,1]
    B: [3,2,1,4,7]
    输出: 3
    解释: 
    长度最长的公共子数组是 [3, 2, 1]。
    

    说明:

    1. 1 <= len(A), len(B) <= 1000
    2. 0 <= A[i], B[i] < 100

    解法

    Python3

    
    

    Java

    class Solution {
        public int findLength(int[] A, int[] B) {
            int ans = 0;
            int[][] dp = new int[A.length + 1][B.length + 1];
            for (int i = 1;i <= A.length;i++) {
                for (int j = 1;j <= B.length;j++) {
                    if (A[i - 1] == B[j - 1]) {
                        dp[i][j] = dp[i - 1][j - 1] + 1;
                        ans = Math.max(ans, dp[i][j]);
                    } else {
                        dp[i][j] = 0;
                    }
                }
            }
            return ans;
        }
    }
    

    
    

    724. 寻找数组的中心索引

    English Version

    题目描述

    给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。

    我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。

    如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。

    示例 1:

    输入: 
    nums = [1, 7, 3, 6, 5, 6]
    输出: 3
    解释: 
    索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
    同时, 3 也是第一个符合要求的中心索引。
    

    示例 2:

    输入: 
    nums = [1, 2, 3]
    输出: -1
    解释: 
    数组中不存在满足此条件的中心索引。

    说明:

    • nums 的长度范围为 [0, 10000]
    • 任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。

    解法

    Python3

    
    

    Java

    class Solution {
        public int pivotIndex(int[] nums) {
            int sum = Arrays.stream(nums).sum();
            int s = 0;
            for (int i = 0; i < nums.length; ++i) {
                if (s << 1 == sum - nums[i]) {
                    return i;
                }
                s += nums[i];
            }
            return -1;
        }
    }
    
    

    
    

    725. 分隔链表

    English Version

    题目描述

    给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分。

    每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 null。

    这k个部分应该按照在链表中出现的顺序进行输出,并且排在前面的部分的长度应该大于或等于后面的长度。

    返回一个符合上述规则的链表的列表。

    举例: 1->2->3->4, k = 5 // 5 结果 [ [1], [2], [3], [4], null ]

    示例 1:

    输入: 
    root = [1, 2, 3], k = 5
    输出: [[1],[2],[3],[],[]]
    解释:
    输入输出各部分都应该是链表,而不是数组。
    例如, 输入的结点 root 的 val= 1, root.next.val = 2, \root.next.next.val = 3, 且 root.next.next.next = null。
    第一个输出 output[0] 是 output[0].val = 1, output[0].next = null。
    最后一个元素 output[4] 为 null, 它代表了最后一个部分为空链表。
    

    示例 2:

    输入: 
    root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3
    输出: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
    解释:
    输入被分成了几个连续的部分,并且每部分的长度相差不超过1.前面部分的长度大于等于后面部分的长度。
    

     

    提示:

    • root 的长度范围: [0, 1000].
    • 输入的每个节点的大小范围:[0, 999].
    • k 的取值范围: [1, 50].

     

    解法

    Python3

    
    

    Java

    class Solution {
        public ListNode[] splitListToParts(ListNode root, int k) {
            ListNode[] res = new ListNode[k];
            int n = getLength(root);
            int len = n / k, left = n % k;
            ListNode pre = null;    // 记录链尾
            for (int i = 0; i < k && root != null; ++i) {
                res[i] = root;
                int step = len;
                if (left > 0) {
                    --left;
                    ++step;
                }
                for (int j = 0; j < step; ++j) {
                    pre = root;
                    root = root.next;
                }
                pre.next = null;    // 断链
            }
            return res;
        }
    
        private int getLength(ListNode root) {
            int res = 0;
            while (root != null) {
                ++res;
                root = root.next;
            }
            return res;
        }
    }
    
    

    
    

    739. 每日温度

    English Version

    题目描述

    根据每日 气温 列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。

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

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

    解法

    栈实现,栈存放 T 中元素的的下标 i,结果用数组 res 存储。

    遍历 T,遍历到 T[i] 时:

    • 若栈不为空,并且栈顶元素小于 T[i] 时,弹出栈顶元素 j,并且 res[j] 赋值为 i - j
    • 然后将 i 压入栈中。

    最后返回结果数组 res 即可。

    Python3

    class Solution:
        def dailyTemperatures(self, T: List[int]) -> List[int]:
            n = len(T)
            res = [0 for _ in range(n)]
            s = []
            for i in range(n):
                while s and T[s[-1]] < T[i]:
                    j = s.pop()
                    res[j] = i - j
                s.append(i)
            return res
    

    Java

    class Solution {
        public int[] dailyTemperatures(int[] T) {
            int n = T.length;
            int[] res = new int[n];
            Deque<Integer> s = new ArrayDeque<>();
            for (int i = 0; i < n; ++i) {
                while (!s.isEmpty() && T[s.peek()] < T[i]) {
                    int j = s.pop();
                    res[j] = i - j;
                }
                s.push(i);
            }
            return res;
        }
    }
    

    
    

    740. 删除与获得点数

    English Version

    题目描述

    给定一个整数数组 nums ,你可以对它进行一些操作。

    每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除每个等于 nums[i] - 1 或 nums[i] + 1 的元素。

    开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

    示例 1:

    输入: nums = [3, 4, 2]
    输出: 6
    解释: 
    删除 4 来获得 4 个点数,因此 3 也被删除。
    之后,删除 2 来获得 2 个点数。总共获得 6 个点数。
    

    示例 2:

    输入: nums = [2, 2, 3, 3, 3, 4]
    输出: 9
    解释: 
    删除 3 来获得 3 个点数,接着要删除两个 2 和 4 。
    之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
    总共获得 9 个点数。
    

    注意:

    • nums的长度最大为20000
    • 每个整数nums[i]的大小都在[1, 10000]范围内。

    解法

    核心思路: 一个数字要么不选,要么全选

    首先计算出每个数字的总和 sums,并维护两个 dp 数组:select 和 nonSelect

    • sums[i] 代表值为 i 的元素总和
    • select[i] 代表如果选数字 i,从 0 处理到 i 的最大和
    • nonSelect[i] 代表如果不选数字 i,从 0 处理到 i 的最大和

    那么我们有以下逻辑:

    • 如果选 i,那么 i-1 肯定不能选;
    • 如果不选 i,那么 i-1 选不选都可以,因此我们选择其中较大的选法
    select[i] = nonSelect[i-1] + sums[i];
    nonSelect[i] = Math.max(select[i-1], nonSelect[i-1]);
    

    Python3

    
    

    Java

    class Solution {
        public int deleteAndEarn(int[] nums) {
            if (nums.length == 0) {
                return 0;
            }
    
            int[] sums = new int[10010];
            int[] select = new int[10010];
            int[] nonSelect = new int[10010];
    
            int maxV = 0;
            for (int x : nums) {
                sums[x] += x;
                maxV = Math.max(maxV, x);
            }
    
            for (int i = 1; i <= maxV; i++) {
                select[i] = nonSelect[i - 1] + sums[i];
                nonSelect[i] = Math.max(select[i - 1], nonSelect[i - 1]);
            }
            return Math.max(select[maxV], nonSelect[maxV]);
        }
    }
    

    
    

    746. 使用最小花费爬楼梯

    English Version

    题目描述

    数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i](索引从0开始)。

    每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。

    您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。

    示例 1:

    输入: cost = [10, 15, 20]
    输出: 15
    解释: 最低花费是从cost[1]开始,然后走两步即可到阶梯顶,一共花费15。
    

     示例 2:

    输入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
    输出: 6
    解释: 最低花费方式是从cost[0]开始,逐个经过那些1,跳过cost[3],一共花费6。
    

    注意:

    1. cost 的长度将会在 [2, 1000]
    2. 每一个 cost[i] 将会是一个Integer类型,范围为 [0, 999]

    解法

    Python3

    class Solution:
        def minCostClimbingStairs(self, cost: List[int]) -> int:
            pre = cur = 0
            n = len(cost)
            for i in range(1, n):
                t = min(cost[i] + cur, cost[i - 1] + pre)
                pre, cur = cur, t
            return cur
    

    Java

    class Solution {
        public int minCostClimbingStairs(int[] cost) {
            int pre = 0, cur = 0;
            for (int i = 1, n = cost.length; i < n; ++i) {
                int t = Math.min(cost[i] + cur, cost[i - 1] + pre);
                pre = cur;
                cur = t;
            }
            return cur;
        }
    }
    

    
    

    752. 打开转盘锁

    English Version

    题目描述

    你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每个拨轮可以自由旋转:例如把 '9' 变为  '0''0' 变为 '9' 。每次旋转都只能旋转一个拨轮的一位数字。

    锁的初始数字为 '0000' ,一个代表四个拨轮的数字的字符串。

    列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。

    字符串 target 代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回 -1。

     

    示例 1:

    输入:deadends = ["0201","0101","0102","1212","2002"], target = "0202"
    输出:6
    解释:
    可能的移动序列为 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。
    注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 这样的序列是不能解锁的,
    因为当拨动到 "0102" 时这个锁就会被锁定。
    

    示例 2:

    输入: deadends = ["8888"], target = "0009"
    输出:1
    解释:
    把最后一位反向旋转一次即可 "0000" -> "0009"。
    

    示例 3:

    输入: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
    输出:-1
    解释:
    无法旋转到目标数字且不被锁定。
    

    示例 4:

    输入: deadends = ["0000"], target = "8888"
    输出:-1
    

     

    提示:

    1. 死亡列表 deadends 的长度范围为 [1, 500]
    2. 目标数字 target 不会在 deadends 之中。
    3. 每个 deadendstarget 中的字符串的数字会在 10,000 个可能的情况 '0000''9999' 中产生。

    解法

    Python3

    
    

    Java

    class Solution {
        public int openLock(String[] deadends, String target) {
            Set<String> begins = new HashSet<>();
            Set<String> deads = new HashSet<>(Arrays.asList(deadends));
            int step = 0;
    
            begins.add("0000");
            if (begins.contains(target)) {
                return step;
            }
    
            while (!begins.isEmpty()) {
                if (begins.contains(target)) {
                    return step;
                }
    
                Set<String> temp = new HashSet<>();
    
                for (String cur : begins) {
                    if (deads.contains(cur)) {
                        continue;
                    }
                    deads.add(cur);
                    StringBuffer s = new StringBuffer(cur);
                    for (int i = 0; i < 4; i++) {
                        char c = s.charAt(i);
                        String s1 = s.substring(0, i) + (char)(c == '9' ? '0' : c + 1) + s.substring(i + 1, 4);
                        String s2 = s.substring(0, i) + (char)(c == '0' ? '9' : c - 1) + s.substring(i + 1, 4);
                        if (!deads.contains(s1)) {
                            temp.add(s1);
                        }
                        if (!deads.contains(s2)) {
                            temp.add(s2);
                        }
                    }
                }
                step ++;
                begins = temp;
            }
    
            return -1;
        }
    }
    
    

    
    

    760. 找出变位映射

    English Version

    题目描述

    给定两个列表 Aand B,并且 BA 的变位(即 B 是由 A 中的元素随机排列后组成的新列表)。

    我们希望找出一个从 AB 的索引映射 P 。一个映射 P[i] = j 指的是列表 A 中的第 i 个元素出现于列表 B 中的第 j 个元素上。

    列表 AB 可能出现重复元素。如果有多于一种答案,输出任意一种。

    例如,给定

    A = [12, 28, 46, 32, 50]
    B = [50, 12, 32, 46, 28]
    

    需要返回

    [1, 4, 3, 2, 0]
    

    P[0] = 1 ,因为 A 中的第 0 个元素出现于 B[1],而且 P[1] = 4 因为 A 中第 1 个元素出现于 B[4],以此类推。

    注:

    1. A, B 有相同的长度,范围为 [1, 100]
    2. A[i], B[i] 都是范围在 [0, 10^5] 的整数。

    解法

    Python3

    
    

    Java

    import java.util.*;
    
    class Solution {
        public int[] anagramMappings(int[] A, int[] B) {
            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < B.length; i++) {
                map.put(B[i], i);
            }
            int[] res = new int[B.length];
            int j = 0;
            for (int k : A) {
                res[j++] = map.get(k);
            }
            return res;
        }
    }
    

    
    

    766. 托普利茨矩阵

    English Version

    题目描述

    如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵

    给定一个 M x N 的矩阵,当且仅当它是托普利茨矩阵时返回 True

    示例 1:

    输入: 
    matrix = [
      [1,2,3,4],
      [5,1,2,3],
      [9,5,1,2]
    ]
    输出: True
    解释:
    在上述矩阵中, 其对角线为:
    "[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]"。
    各条对角线上的所有元素均相同, 因此答案是True。
    

    示例 2:

    输入:
    matrix = [
      [1,2],
      [2,2]
    ]
    输出: False
    解释: 
    对角线"[1, 2]"上的元素不同。
    

    说明:

    1.  matrix 是一个包含整数的二维数组。
    2. matrix 的行数和列数均在 [1, 20]范围内。
    3. matrix[i][j] 包含的整数在 [0, 99]范围内。

    进阶:

    1. 如果矩阵存储在磁盘上,并且磁盘内存是有限的,因此一次最多只能将一行矩阵加载到内存中,该怎么办?
    2. 如果矩阵太大以至于只能一次将部分行加载到内存中,该怎么办?

    解法

    遍历矩阵,若出现元素与其左上角的元素不等的情况,返回 false

    Python3

    class Solution:
        def isToeplitzMatrix(self, matrix: List[List[int]]) -> bool:
            m, n = len(matrix), len(matrix[0])
            for i in range(1, m):
                for j in range(1, n):
                    if matrix[i][j] != matrix[i - 1][j - 1]:
                        return False
            return True
    

    Java

    class Solution {
        public boolean isToeplitzMatrix(int[][] matrix) {
            int m = matrix.length, n = matrix[0].length;
            for (int i = 1; i < m; ++i) {
                for (int j = 1; j < n; ++j) {
                    if (matrix[i][j] != matrix[i - 1][j - 1]) {
                        return false;
                    }
                }
            }
            return true;
        }
    }
    

    
    

    771. 宝石与石头

    English Version

    题目描述

     给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。

    J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a""A"是不同类型的石头。

    示例 1:

    输入: J = "aA", S = "aAAbbbb"
    输出: 3
    

    示例 2:

    输入: J = "z", S = "ZZ"
    输出: 0
    

    注意:

    • S 和 J 最多含有50个字母。
    •  J 中的字符不重复。

    解法

    Python3

    
    

    Java

    class Solution {
        public int numJewelsInStones(String J, String S) {
            Set<Character> set = new HashSet<>();
            for (char ch : J.toCharArray()) {
                set.add(ch);
            }
            int res = 0;
            for (char ch : S.toCharArray()) {
                res += (set.contains(ch) ? 1 : 0);
            }
            return res;
        }
    }
    

    
    

    777. 在 LR 字符串中交换相邻字符

    English Version

    题目描述

    在一个由 'L' , 'R''X' 三个字符组成的字符串(例如"RXXLRXRXL")中进行移动操作。一次移动操作指用一个"LX"替换一个"XL",或者用一个"XR"替换一个"RX"。现给定起始字符串start和结束字符串end,请编写代码,当且仅当存在一系列移动操作使得start可以转换成end时, 返回True

    示例 :

    输入: start = "RXXLRXRXL", end = "XRLXXRRLX"
    输出: True
    解释:
    我们可以通过以下几步将start转换成end:
    RXXLRXRXL ->
    XRXLRXRXL ->
    XRLXRXRXL ->
    XRLXXRRXL ->
    XRLXXRRLX
    

    注意:

    1. 1 <= len(start) = len(end) <= 10000
    2. startend中的字符串仅限于'L', 'R''X'

    解法

    Python3

    
    

    Java

    class Solution {
        public boolean canTransform(String start, String end) {
            if (start.length() != end.length()) {
                return false;
            }
            int i = 0, j = 0;
            while (true) {
                while (i < start.length() && start.charAt(i) == 'X') {
                    ++i;
                }
                while (j < end.length() && end.charAt(j) == 'X') {
                    ++j;
                }
                if (i == start.length() && j == start.length()) {
                    return true;
                }
                if (i == start.length() || j == start.length() || start.charAt(i) != end.charAt(j)) {
                    return false;
                }
                if (start.charAt(i) == 'L' && i < j || start.charAt(i) == 'R'  && i > j) {
                    return false;
                }
                ++i;
                ++j;
            }
        }
    }
    
    

    
    

    783. 二叉搜索树结点最小距离

    English Version

    题目描述

    给定一个二叉搜索树的根结点 root,返回树中任意两节点的差的最小值。

     

    示例:

    输入: root = [4,2,6,1,3,null,null]
    输出: 1
    解释:
    注意,root是树结点对象(TreeNode object),而不是数组。
    
    给定的树 [4,2,6,1,3,null,null] 可表示为下图:
    
              4
            /   \
          2      6
         / \    
        1   3  
    
    最小的差值是 1, 它是节点1和节点2的差值, 也是节点3和节点2的差值。

     

    注意:

    1. 二叉树的大小范围在 2 到 100
    2. 二叉树总是有效的,每个节点的值都是整数,且不重复。
    3. 本题与 530:https://leetcode-cn.com/problems/minimum-absolute-difference-in-bst/ 相同

    解法

    Python3

    
    

    Java

    
    

    Go

    /**
     * Definition for a binary tree node.
     * type TreeNode struct {
     *     Val int
     *     Left *TreeNode
     *     Right *TreeNode
     * }
     */
    
    var res int
    var preNode *TreeNode
    func minDiffInBST(root *TreeNode) int {
        res = int(^uint(0) >> 1)
        preNode = nil
        helper(root)
        return res
    }
    
    func helper(root *TreeNode)  {
        if root == nil {
            return
        }
        helper(root.Left)
        if preNode != nil {
            res = getMinInt(res, root.Val - preNode.Val)
        }
        preNode = root
        helper(root.Right)
    }
    
    func getMinInt(a,b int) int {
        if a < b {
            return a
        }
        return b
    }
    

    Java

    class Solution {
        public int minDiffInBST(TreeNode root) {
            TreeNode[] pre = new TreeNode[1];
            int[] res = new int[]{Integer.MAX_VALUE};
            dfs(root, pre, res);
            return res[0];
        }
    
        private void dfs(TreeNode root, TreeNode[] pre, int[] res) {
            if (root == null) {
                return;
            }
            dfs(root.left, pre, res);
            if (pre[0] != null) {
                res[0] = Math.min(res[0], root.val - pre[0].val);
            }
            pre[0] = root;
            dfs(root.right, pre, res);
        }
    }
    
    

    784. 字母大小写全排列

    English Version

    题目描述

    给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。

    示例:
    输入: S = "a1b2"
    输出: ["a1b2", "a1B2", "A1b2", "A1B2"]
    
    输入: S = "3z4"
    输出: ["3z4", "3Z4"]
    
    输入: S = "12345"
    输出: ["12345"]
    

    注意:

    • S 的长度不超过12
    • S 仅由数字和字母组成。

    解法

    Python3

    
    

    Java

    class Solution {
        public List<String> letterCasePermutation(String S) {
            char[] cs = S.toCharArray();
            List<String> res = new ArrayList<>();
            dfs(cs, 0, res);
            return res;
        }
    
        private void dfs(char[] cs, int i, List<String> res) {
            if (i == cs.length) {
                res.add(String.valueOf(cs));
                return;
            }
            dfs(cs, i + 1, res);
            if (cs[i] >= 'A') {
                cs[i] ^= 32;
                dfs(cs, i + 1, res);
            }
        }
    }
    
    

    
    

    814. 二叉树剪枝

    English Version

    题目描述

    给定二叉树根结点 root ,此外树的每个结点的值要么是 0,要么是 1。

    返回移除了所有不包含 1 的子树的原二叉树。

    ( 节点 X 的子树为 X 本身,以及所有 X 的后代。)

    示例1:
    输入: [1,null,0,0,1]
    输出: [1,null,0,null,1]
     
    解释: 
    只有红色节点满足条件“所有不包含 1 的子树”。
    右图为返回的答案。
    

    在这里插入图片描述

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

    在这里插入图片描述

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

    在这里插入图片描述

    说明:

    • 给定的二叉树最多有 100 个节点。
    • 每个节点的值只会为 0 或 1 。

    解法

    Python3

    
    

    Java

    class Solution {
        public TreeNode pruneTree(TreeNode root) {
            if (root == null) {
                return null;
            }
            root.left = pruneTree(root.left);
            root.right = pruneTree(root.right);
            return root.val == 0 && root.left == null && root.right == null ? null : root;
        }
    }
    
    

    
    

    817. 链表组件

    English Version

    题目描述

    给定一个链表(链表结点包含一个整型值)的头结点 head

    同时给定列表 G,该列表是上述链表中整型值的一个子集。

    返回列表 G 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 G 中)构成的集合。

    示例 1:

    输入: 
    head: 0->1->2->3
    G = [0, 1, 3]
    输出: 2
    解释: 
    链表中,0 和 1 是相连接的,且 G 中不包含 2,所以 [0, 1] 是 G 的一个组件,同理 [3] 也是一个组件,故返回 2。

    示例 2:

    输入: 
    head: 0->1->2->3->4
    G = [0, 3, 1, 4]
    输出: 2
    解释: 
    链表中,0 和 1 是相连接的,3 和 4 是相连接的,所以 [0, 1] 和 [3, 4] 是两个组件,故返回 2。

    注意:

    • 如果 N 是给定链表 head 的长度,1 <= N <= 10000
    • 链表中每个结点的值所在范围为 [0, N - 1]
    • 1 <= G.length <= 10000
    • G 是链表中所有结点的值的一个子集.

    解法

    Python3

    
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public int numComponents(ListNode head, int[] G) {
            if (head == null || G == null) {
                return 0;
            }
            Set<Integer> set = new HashSet<>();
            for (int val : G) {
                set.add(val);
            }
            int n = G.length;
            ListNode cur = head;
            int cnt = 0;
            boolean flag = false;
            while (cur != null) {
                while (cur != null && set.contains(cur.val)) {
                    flag = true;
                    cur = cur.next;
                }
                if (flag) {
                    ++cnt;
                    flag = false;
                }
                
                if (cur != null) {
                    cur = cur.next;
                }
            }
            return cnt;
        }
    }
    

    
    

    829. 连续整数求和

    English Version

    题目描述

    给定一个正整数 N,试求有多少组连续正整数满足所有数字之和为 N?

    例 1:

    输入: 5
    输出: 2
    解释: 5 = 5 = 2 + 3,共有两组连续整数([5],[2,3])求和后为 5。

    示例 2:

    输入: 9
    输出: 3
    解释: 9 = 9 = 4 + 5 = 2 + 3 + 4

    示例 3:

    输入: 15
    输出: 4
    解释: 15 = 15 = 8 + 7 = 4 + 5 + 6 = 1 + 2 + 3 + 4 + 5

    说明: 1 <= N <= 10 ^ 9

    解法

    Python3

    
    

    Java

    class Solution {
        public int consecutiveNumbersSum(int N) {
            int res = 0;
            for (int i = 1; i * (i - 1) / 2 < N; ++i) {
                if ((N - i * (i - 1) / 2) % i == 0) {
                    ++res;
                }
            }
            return res;
        }
    }
    
    

    
    

    832. 翻转图像

    English Version

    题目描述

    给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。

    水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]

    反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0, 1, 1] 的结果是 [1, 0, 0]

    示例 1:

    输入: [[1,1,0],[1,0,1],[0,0,0]]
    输出: [[1,0,0],[0,1,0],[1,1,1]]
    解释: 首先翻转每一行: [[0,1,1],[1,0,1],[0,0,0]];
         然后反转图片: [[1,0,0],[0,1,0],[1,1,1]]
    

    示例 2:

    输入: [[1,1,0,0],[1,0,0,1],[0,1,1,1],[1,0,1,0]]
    输出: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]
    解释: 首先翻转每一行: [[0,0,1,1],[1,0,0,1],[1,1,1,0],[0,1,0,1]];
         然后反转图片: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]
    

    说明:

    • 1 <= A.length = A[0].length <= 20
    • 0 <= A[i][j] <= 1

    解法

    遍历矩阵每一行,利用双指针 p, q 进行水平交换翻转,顺便反转图像(1 变 0,0 变 1:1 ^ 1 = 0,0 ^ 1 = 1)。

    Python3

    class Solution:
        def flipAndInvertImage(self, A: List[List[int]]) -> List[List[int]]:
            m, n = len(A), len(A[0])
            for i in range(m):
                p, q = 0, n - 1
                while p < q:
                    t = A[i][p] ^ 1
                    A[i][p] = A[i][q] ^ 1
                    A[i][q] = t
                    p += 1
                    q -= 1
                if p == q:
                    A[i][p] ^= 1
            return A
    

    Java

    class Solution {
        public int[][] flipAndInvertImage(int[][] A) {
            int m = A.length, n = A[0].length;
            for (int i = 0; i < m; ++i) {
                int p = 0, q = n - 1;
                while (p < q) {
                    int t = A[i][p] ^ 1;
                    A[i][p] = A[i][q] ^ 1;
                    A[i][q] = t;
                    ++p;
                    --q;
                }
                if (p == q) {
                    A[i][p] ^= 1;
                }
            }
            return A;
        }
    }
    

    C++

    class Solution {
    public:
        vector<vector<int>> flipAndInvertImage(vector<vector<int>>& A) {
            int m = A.size(), n = A[0].size();
            for (int i = 0; i < m; ++i) {
                int p = 0, q = n - 1;
                while (p < q) {
                    int t = A[i][p] ^ 1;
                    A[i][p] = A[i][q] ^ 1;
                    A[i][q] = t;
                    ++p;
                    --q;
                }
                if (p == q) {
                    A[i][p] ^= 1;
                }
            }
            return A;
        }
    };
    

    
    

    852. 山脉数组的峰顶索引

    English Version

    题目描述

    我们把符合下列属性的数组 A 称作山脉:

    • A.length >= 3
    • 存在 0 < i < A.length - 1 使得A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]

    给定一个确定为山脉的数组,返回任何满足 A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 的 i 的值。

     

    示例 1:

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

    示例 2:

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

     

    提示:

    1. 3 <= A.length <= 10000
    2. 0 <= A[i] <= 10^6
    3. A 是如上定义的山脉

     

    解法

    Python3

    
    

    Java

    class Solution {
        public int peakIndexInMountainArray(int[] A) {
            int l = 0, r = A.length - 1;
            while (l < r) {
                int mid = l + r >>> 1;
                if (A[mid] > A[mid + 1]) r = mid;
                else l = mid + 1;
            }
            return r;
        }
    }
    
    

    
    

    856. 括号的分数

    English Version

    题目描述

    给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:

    • () 得 1 分。
    • AB 得 A + B 分,其中 A 和 B 是平衡括号字符串。
    • (A) 得 2 * A 分,其中 A 是平衡括号字符串。

     

    示例 1:

    输入: "()"
    输出: 1
    

    示例 2:

    输入: "(())"
    输出: 2
    

    示例 3:

    输入: "()()"
    输出: 2
    

    示例 4:

    输入: "(()(()))"
    输出: 6
    

     

    提示:

    1. S 是平衡括号字符串,且只含有 ( 和 ) 。
    2. 2 <= S.length <= 50

    解法

    Python3

    
    

    Java

    class Solution {
        public int scoreOfParentheses(String S) {
            int res = 0;
            for (int i = 0, d = 0; i < S.length(); ++i) {
                if (S.charAt(i) == '(') {
                    ++d;
                } else {
                    --d;
                    if (S.charAt(i - 1) == '(') {
                        res += 1 << d;
                    }
                }
            }
            return res;
        }
    }
    
    

    
    

    857. 雇佣 K 名工人的最低成本

    English Version

    题目描述

    N 名工人。 第 i 名工人的工作质量为 quality[i] ,其最低期望工资为 wage[i] 。

    现在我们想雇佣 K 名工人组成一个工资组。在雇佣 一组 K 名工人时,我们必须按照下述规则向他们支付工资:

    1. 对工资组中的每名工人,应当按其工作质量与同组其他工人的工作质量的比例来支付工资。
    2. 工资组中的每名工人至少应当得到他们的最低期望工资。

    返回组成一个满足上述条件的工资组至少需要多少钱。

     

      示例 1:

      输入: quality = [10,20,5], wage = [70,50,30], K = 2
      输出: 105.00000
      解释: 我们向 0 号工人支付 70,向 2 号工人支付 35。

      示例 2:

      输入: quality = [3,1,10,10,1], wage = [4,8,2,2,7], K = 3
      输出: 30.66667
      解释: 我们向 0 号工人支付 4,向 2 号和 3 号分别支付 13.33333。

       

      提示:

      1. 1 <= K <= N <= 10000,其中 N = quality.length = wage.length
      2. 1 <= quality[i] <= 10000
      3. 1 <= wage[i] <= 10000
      4. 与正确答案误差在 10^-5 之内的答案将被视为正确的。

      解法

      Python3

      
      

      Java

      class Solution {
          public double mincostToHireWorkers(int[] quality, int[] wage, int K) {
              Worker[] workers = new Worker[quality.length];
              for (int i = 0; i < quality.length; ++i) {
                  workers[i] = new Worker((double) wage[i] / quality[i], quality[i]);
              }
              Arrays.sort(workers);
              double res = 1e9;
              Queue<Integer> queue = new PriorityQueue<>(Comparator.reverseOrder());
              int s = 0;
              for (Worker worker : workers) {
                  s += worker.quality;
                  queue.offer(worker.quality);
                  if (queue.size() > K) {
                      s -= queue.poll();
                  }
                  if (queue.size() == K) {
                      res = Math.min(res, s * worker.x);
                  }
              }
              return res;
          }
      
          class Worker implements Comparable<Worker> {
              double x;
              int quality;
      
              public Worker(double x, int quality) {
                  this.x = x;
                  this.quality = quality;
              }
      
              @Override
              public int compareTo(Worker o) {
                  return Double.compare(x, o.x);
              }
          }
      }
      
      

      
      

      860. 柠檬水找零

      English Version

      题目描述

      在柠檬水摊上,每一杯柠檬水的售价为 5 美元。

      顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

      每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

      注意,一开始你手头没有任何零钱。

      如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

      示例 1:

      输入:[5,5,5,10,20]
      输出:true
      解释:
      前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
      第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
      第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
      由于所有客户都得到了正确的找零,所以我们输出 true。
      

      示例 2:

      输入:[5,5,10]
      输出:true
      

      示例 3:

      输入:[10,10]
      输出:false
      

      示例 4:

      输入:[5,5,10,10,20]
      输出:false
      解释:
      前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
      对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
      对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
      由于不是每位顾客都得到了正确的找零,所以答案是 false。
      

       

      提示:

      • 0 <= bills.length <= 10000
      • bills[i] 不是 5 就是 10 或是 20 

      解法

      Python3

      
      

      Java

      class Solution {
          public boolean lemonadeChange(int[] bills) {
              int fives = 0, tens = 0;
              for (int bill : bills) {
                  if (bill == 5) {
                      ++fives;
                  } else if (bill == 10) {
                      ++tens;
                      if (--fives < 0) {
                          return false;
                      }
                  } else {
                      if (tens >= 1 && fives >= 1) {
                          --tens;
                          --fives;
                      } else if (fives >= 3) {
                          fives -= 3;
                      } else {
                          return false;
                      }
                  }
              }
              return true;
          }
      }
      
      

      
      

      862. 和至少为 K 的最短子数组

      English Version

      题目描述

      返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K

      如果没有和至少为 K 的非空子数组,返回 -1 。

       

        示例 1:

        输入:A = [1], K = 1
        输出:1
        

        示例 2:

        输入:A = [1,2], K = 4
        输出:-1
        

        示例 3:

        输入:A = [2,-1,2], K = 3
        输出:3
        

         

        提示:

        1. 1 <= A.length <= 50000
        2. -10 ^ 5 <= A[i] <= 10 ^ 5
        3. 1 <= K <= 10 ^ 9

        解法

        Python3

        
        

        Java

        class Solution {
            public int shortestSubarray(int[] A, int K) {
                int n = A.length;
                int[] s = new int[n + 1];
                for (int i = 0; i < n; ++i) {
                    s[i + 1] = s[i] + A[i];
                }
                Deque<Integer> deque = new ArrayDeque<>();
                deque.offer(0);
                int res = Integer.MAX_VALUE;
                for (int i = 1; i <= n; ++i) {
                    while (!deque.isEmpty() && s[i] - s[deque.peekFirst()] >= K) {
                        res = Math.min(res, i - deque.pollFirst());
                    }
                    while (!deque.isEmpty() && s[i] <= s[deque.peekLast()]) {
                        deque.pollLast();
                    }
                    deque.offer(i);
                }
                return res != Integer.MAX_VALUE ? res : -1;
            }
        }
        
        

        
        

        872. 叶子相似的树

        English Version

        题目描述

        请考虑一颗二叉树上所有的叶子,这些叶子的值按从左到右的顺序排列形成一个 叶值序列

        在这里插入图片描述

        举个例子,如上图所示,给定一颗叶值序列为 (6, 7, 4, 9, 8) 的树。

        如果有两颗二叉树的叶值序列是相同,那么我们就认为它们是 叶相似 的。

        如果给定的两个头结点分别为 root1 和 root2 的树是叶相似的,则返回 true;否则返回 false

         

        提示:

        • 给定的两颗树可能会有 1 到 100 个结点。

        解法

        深度优先搜索。

        Python3

        # Definition for a binary tree node.
        # class TreeNode:
        #     def __init__(self, val=0, left=None, right=None):
        #         self.val = val
        #         self.left = left
        #         self.right = right
        class Solution:
            def leafSimilar(self, root1: TreeNode, root2: TreeNode) -> bool:
                def dfs(root, leaves):
                    if root is None:
                        return
                    if root.left is None and root.right is None:
                        leaves.append(root.val)
                        return
                    dfs(root.left, leaves)
                    dfs(root.right, leaves)
                l1, l2 = [], []
                dfs(root1, l1)
                dfs(root2, l2)
                return l1 == l2
        

        Java

        /**
         * Definition for a binary tree node.
         * public class TreeNode {
         *     int val;
         *     TreeNode left;
         *     TreeNode right;
         *     TreeNode() {}
         *     TreeNode(int val) { this.val = val; }
         *     TreeNode(int val, TreeNode left, TreeNode right) {
         *         this.val = val;
         *         this.left = left;
         *         this.right = right;
         *     }
         * }
         */
        class Solution {
            public boolean leafSimilar(TreeNode root1, TreeNode root2) {
                List<Integer> l1 = new ArrayList<>();
                List<Integer> l2 = new ArrayList<>();
                dfs(root1, l1);
                dfs(root2, l2);
                return l1.equals(l2);
            }
        
            private void dfs(TreeNode root, List<Integer> leaves) {
                if (root == null) return;
                if (root.left == null && root.right == null) {
                    leaves.add(root.val);
                    return;
                }
                dfs(root.left, leaves);
                dfs(root.right, leaves);
            }
        }
        

        
        

        875. 爱吃香蕉的珂珂

        English Version

        题目描述

        珂珂喜欢吃香蕉。这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 H 小时后回来。

        珂珂可以决定她吃香蕉的速度 K (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 K 根。如果这堆香蕉少于 K 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。  

        珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。

        返回她可以在 H 小时内吃掉所有香蕉的最小速度 KK 为整数)。

         

          示例 1:

          输入: piles = [3,6,7,11], H = 8
          输出: 4
          

          示例 2:

          输入: piles = [30,11,23,4,20], H = 5
          输出: 30
          

          示例 3:

          输入: piles = [30,11,23,4,20], H = 6
          输出: 23
          

           

          提示:

          • 1 <= piles.length <= 10^4
          • piles.length <= H <= 10^9
          • 1 <= piles[i] <= 10^9

          解法

          Python3

          
          

          Java

          class Solution {
              public int minEatingSpeed(int[] piles, int H) {
                  int l = 1, r = 1000000000;
                  while (l < r) {
                      int mid = l + r >>> 1;
                      if (check(piles, H, mid)) r = mid;
                      else l = mid + 1;
                  }
                  return r;
              }
          
              private boolean check(int[] piles, int h, int k) {
                  int cnt = 0;
                  for (int pile : piles) {
                      cnt += (pile - 1) / k + 1;
                  }
                  return cnt <= h;
              }
          }
          
          

          
          

          876. 链表的中间结点

          English Version

          题目描述

          给定一个带有头结点 head 的非空单链表,返回链表的中间结点。

          如果有两个中间结点,则返回第二个中间结点。

           

          示例 1:

          输入:[1,2,3,4,5]
          输出:此列表中的结点 3 (序列化形式:[3,4,5])
          返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
          注意,我们返回了一个 ListNode 类型的对象 ans,这样:
          ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
          

          示例 2:

          输入:[1,2,3,4,5,6]
          输出:此列表中的结点 4 (序列化形式:[4,5,6])
          由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
          

           

          提示:

          • 给定链表的结点数介于 1 和 100 之间。

          解法

          Python3

          
          

          Java

          public ListNode middleNode(ListNode head) {
              ListNode low = head, first = head;
              while (first != null && first.next != null) {
                  low = low.next;
                  first = first.next.next;
              }
              return low;
          }
          

          
          

          878. 第 N 个神奇数字

          English Version

          题目描述

          如果正整数可以被 A 或 B 整除,那么它是神奇的。

          返回第 N 个神奇数字。由于答案可能非常大,返回它模 10^9 + 7 的结果

           

            示例 1:

            输入:N = 1, A = 2, B = 3
            输出:2
            

            示例 2:

            输入:N = 4, A = 2, B = 3
            输出:6
            

            示例 3:

            输入:N = 5, A = 2, B = 4
            输出:10
            

            示例 4:

            输入:N = 3, A = 6, B = 4
            输出:8
            

             

            提示:

            1. 1 <= N <= 10^9
            2. 2 <= A <= 40000
            3. 2 <= B <= 40000

            解法

            Python3

            
            

            Java

            class Solution {
                public int nthMagicalNumber(int N, int A, int B) {
                    long l = 1, r = Long.MAX_VALUE;
                    int lcm = A * B / gcd(A, B);
                    while (l < r) {
                        long mid = l + r >>> 1;
                        if (mid / A + mid / B - mid / lcm >= N) r = mid;
                        else l = mid + 1;
                    }
                    return (int) (r % 1000000007);
                }
            
                private int gcd(int a, int b) {
                    return b == 0 ? a : gcd(b, a % b);
                }
            }
            
            

            
            

            883. 三维形体投影面积

            English Version

            题目描述

            在 N * N 的网格中,我们放置了一些与 x,y,z 三轴对齐的 1 * 1 * 1 立方体。

            每个值 v = grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上。

            现在,我们查看这些立方体在 xy、yz 和 zx 平面上的投影

            投影就像影子,将三维形体映射到一个二维平面上。

            在这里,从顶部、前面和侧面看立方体时,我们会看到“影子”。

            返回所有三个投影的总面积。

             

                    示例 1:

                    输入:[[2]]
                    输出:5
                    

                    示例 2:

                    输入:[[1,2],[3,4]]
                    输出:17
                    解释:
                    这里有该形体在三个轴对齐平面上的三个投影(“阴影部分”)。
                    

                    在这里插入图片描述

                    示例 3:

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

                    示例 4:

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

                    示例 5:

                    输入:[[2,2,2],[2,1,2],[2,2,2]]
                    输出:21
                    

                     

                    提示:

                    • 1 <= grid.length = grid[0].length <= 50
                    • 0 <= grid[i][j] <= 50

                    解法

                    Python3

                    
                    

                    Java

                    class Solution {
                        public int projectionArea(int[][] grid) {
                            int n = grid.length;
                            int res = 0;
                            for (int i = 0; i < n; ++i) {
                                for (int j = 0; j < n; ++j) {
                                    res += grid[i][j] > 0 ? 1 : 0;
                                }
                            }
                            for (int i = 0; i < n; ++i) {
                                int max = 0;
                                for (int j = 0; j < n; ++j) {
                                    max = Math.max(max, grid[i][j]);
                                }
                                res += max;
                            }
                            for (int j = 0; j < n; ++j) {
                                int max = 0;
                                for (int i = 0; i < n; ++i) {
                                    max = Math.max(max, grid[i][j]);
                                }
                                res += max;
                            }
                            return res;
                        }
                    }
                    
                    

                    
                    

                    887. 鸡蛋掉落

                    English Version

                    题目描述

                    你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N  共有 N 层楼的建筑。

                    每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。

                    你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。

                    每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 1 <= X <= N)。

                    你的目标是确切地知道 F 的值是多少。

                    无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?

                     

                      示例 1:

                      输入:K = 1, N = 2
                      输出:2
                      解释:
                      鸡蛋从 1 楼掉落。如果它碎了,我们肯定知道 F = 0 。
                      否则,鸡蛋从 2 楼掉落。如果它碎了,我们肯定知道 F = 1 。
                      如果它没碎,那么我们肯定知道 F = 2 。
                      因此,在最坏的情况下我们需要移动 2 次以确定 F 是多少。
                      

                      示例 2:

                      输入:K = 2, N = 6
                      输出:3
                      

                      示例 3:

                      输入:K = 3, N = 14
                      输出:4
                      

                       

                      提示:

                      1. 1 <= K <= 100
                      2. 1 <= N <= 10000

                      解法

                      Python3

                      
                      

                      Java

                      class Solution {
                          public int superEggDrop(int K, int N) {
                              int[] res = new int[K];
                              Arrays.fill(res, 1);
                              while (res[K - 1] < N) {
                                  for (int i = K - 1; i >= 1; i--) {
                                      res[i] = res[i] + res[i - 1] + 1;
                                  }
                                  res[0]++;
                              }
                              return res[0];
                          }
                      }
                      

                      
                      

                      891. 子序列宽度之和

                      English Version

                      题目描述

                      给定一个整数数组 A ,考虑 A 的所有非空子序列。

                      对于任意序列 S ,设 S 的宽度是 S 的最大元素和最小元素的差。

                      返回 A 的所有子序列的宽度之和。

                      由于答案可能非常大,请返回答案模 10^9+7

                       

                      示例:

                      输入:[2,1,3]
                      输出:6
                      解释:
                      子序列为 [1],[2],[3],[2,1],[2,3],[1,3],[2,1,3] 。
                      相应的宽度是 0,0,0,1,1,2,2 。
                      这些宽度之和是 6 。
                      

                       

                      提示:

                      • 1 <= A.length <= 20000
                      • 1 <= A[i] <= 20000

                      解法

                      Python3

                      
                      

                      Java

                      class Solution {
                          public int sumSubseqWidths(int[] A) {
                              final int MOD = (int) (1e9 + 7);
                              Arrays.sort(A);
                              int n = A.length;
                              long res = 0;
                              long p = 1;
                              for (int i = 0; i < n; ++i) {
                                  res = (res + (A[i] - A[n - 1 - i]) * p) % MOD;
                                  p = (p << 1) % MOD;
                              }
                              return (int) ((res + MOD) % MOD);
                          }
                      }
                      
                      

                      
                      

                      892. 三维形体的表面积

                      English Version

                      题目描述

                      在 N * N 的网格上,我们放置一些 1 * 1 * 1  的立方体。

                      每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。

                      请你返回最终形体的表面积。

                       

                        示例 1:

                        输入:[[2]]
                        输出:10
                        

                        示例 2:

                        输入:[[1,2],[3,4]]
                        输出:34
                        

                        示例 3:

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

                        示例 4:

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

                        示例 5:

                        输入:[[2,2,2],[2,1,2],[2,2,2]]
                        输出:46
                        

                         

                        提示:

                        • 1 <= N <= 50
                        • 0 <= grid[i][j] <= 50

                        解法

                        Python3

                        
                        

                        Java

                        class Solution {
                            public int surfaceArea(int[][] grid) {
                                int n = grid.length;
                                int res = 0;
                                for (int i = 0; i < n; ++i) {
                                    for (int j = 0; j < n; ++j) {
                                        if (grid[i][j] > 0) {
                                            res += 2 + grid[i][j] * 4;
                                            if (i > 0) {
                                                res -= Math.min(grid[i][j], grid[i - 1][j]) * 2;
                                            }
                                            if (j > 0) {
                                                res -= Math.min(grid[i][j], grid[i][j - 1]) * 2;
                                            }
                                        }
                                    }
                                }
                                return res;
                            }
                        }
                        
                        

                        
                        

                        897. 递增顺序查找树

                        English Version

                        题目描述

                        给你一个树,请你 按中序遍历 重新排列树,使树中最左边的结点现在是树的根,并且每个结点没有左子结点,只有一个右子结点。

                         

                        示例 :

                        输入:[5,3,6,2,4,null,8,1,null,null,null,7,9]
                        
                               5
                              / \
                            3    6
                           / \    \
                          2   4    8
                         /        / \ 
                        1        7   9
                        
                        输出:[1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]
                        
                         1
                          \
                           2
                            \
                             3
                              \
                               4
                                \
                                 5
                                  \
                                   6
                                    \
                                     7
                                      \
                                       8
                                        \
                                         9  

                         

                        提示:

                        1. 给定树中的结点数介于 1 和 100 之间。
                        2. 每个结点都有一个从 01000 范围内的唯一整数值。

                        解法

                        递归将左子树、右子树转换为左、右链表 left 和 right。然后将左链表 left 的最后一个结点的 right 指针指向 root,root 的 right 指针指向右链表 right,并将 root 的 left 指针值为空。

                        面试题 17.12. BiNode

                        Python3

                        # Definition for a binary tree node.
                        # class TreeNode:
                        #     def __init__(self, val=0, left=None, right=None):
                        #         self.val = val
                        #         self.left = left
                        #         self.right = right
                        class Solution:
                            def increasingBST(self, root: TreeNode) -> TreeNode:
                                if root is None:
                                    return None
                                left = self.increasingBST(root.left)
                                right = self.increasingBST(root.right)
                                if left is None:
                                    root.right = right
                                    return root
                                res = left
                                while left and left.right:
                                    left = left.right
                                left.right = root
                                root.right = right
                                root.left = None
                                return res
                        

                        Java

                        /**
                         * Definition for a binary tree node.
                         * public class TreeNode {
                         *     int val;
                         *     TreeNode left;
                         *     TreeNode right;
                         *     TreeNode() {}
                         *     TreeNode(int val) { this.val = val; }
                         *     TreeNode(int val, TreeNode left, TreeNode right) {
                         *         this.val = val;
                         *         this.left = left;
                         *         this.right = right;
                         *     }
                         * }
                         */
                        class Solution {
                            public TreeNode increasingBST(TreeNode root) {
                                if (root == null) return null;
                                TreeNode left = increasingBST(root.left);
                                TreeNode right = increasingBST(root.right);
                                if (left == null) {
                                    root.right = right;
                                    return root;
                                }
                                TreeNode res = left;
                                while (left != null && left.right != null) left = left.right;
                                left.right = root;
                                root.right = right;
                                root.left = null;
                                return res;
                            }
                        }
                        

                        
                        

                        898. 子数组按位或操作

                        English Version

                        题目描述

                        我们有一个非负整数数组 A

                        对于每个(连续的)子数组 B = [A[i], A[i+1], ..., A[j]] ( i <= j),我们对 B 中的每个元素进行按位或操作,获得结果 A[i] | A[i+1] | ... | A[j]

                        返回可能结果的数量。 (多次出现的结果在最终答案中仅计算一次。)

                         

                        示例 1:

                        输入:[0]
                        输出:1
                        解释:
                        只有一个可能的结果 0 。
                        

                        示例 2:

                        输入:[1,1,2]
                        输出:3
                        解释:
                        可能的子数组为 [1],[1],[2],[1, 1],[1, 2],[1, 1, 2]。
                        产生的结果为 1,1,2,1,3,3 。
                        有三个唯一值,所以答案是 3 。
                        

                        示例 3:

                        输入:[1,2,4]
                        输出:6
                        解释:
                        可能的结果是 1,2,3,4,6,以及 7 。
                        

                         

                        提示:

                        1. 1 <= A.length <= 50000
                        2. 0 <= A[i] <= 10^9

                        解法

                        Python3

                        
                        

                        Java

                        class Solution {
                            public int subarrayBitwiseORs(int[] A) {
                                int maxVal = Arrays.stream(A).max().getAsInt();
                                int mask = (Integer.highestOneBit(maxVal) << 1) - 1;
                                Set<Integer> res = new HashSet<>();
                                for (int i = 0; i < A.length; ++i) {
                                    int val = A[i];
                                    res.add(val);
                                    for (int j = i - 1; j >= 0 && val != mask; --j) {
                                        val |= A[j];
                                        res.add(val);
                                    }
                                }
                                return res.size();
                            }
                        }
                        
                        

                        
                        
                        • 0
                          点赞
                        • 2
                          收藏
                          觉得还不错? 一键收藏
                        • 0
                          评论
                        KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:

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

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

                        请填写红包祝福语或标题

                        红包个数最小为10个

                        红包金额最低5元

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

                        抵扣说明:

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

                        余额充值