AI刷力扣

 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:点击跳转

目录

2. 两数相加(C++)

4. 寻找两个正序数组的中位数(C++)

5. 最长回文子串(python)

6. N 字形变换(C++)

10. 正则表达式匹配(python)

13. 罗马数字转整数(C++)

16. 最接近的三数之和(python)

17. 电话号码的字母组合(python)

24. 两两交换链表中的节点(C++)

32. 最长有效括号(C++)

38. 外观数列(python)

40. 组合总和 II(C++)

43. 字符串相乘(C++)

44. 通配符匹配(C++)

48. 旋转图像(C++)

57. 插入区间(C++)

65. 有效数字(C++)

68. 文本左右对齐(python)

71. 简化路径(python)

97. 交错字符串(python)

115. 不同的子序列(C++)

127. 单词接龙(C++)

131. 分割回文串(python)

132. 分割回文串 II

166. 分数到小数(C++)

168. Excel表列名称(C++)

171. Excel 表列序号

224. 基本计算器(python)

241. 为运算表达式设计优先级(python)

415. 字符串相加(C++)

592. 分数加减运算(python)

722. 删除注释(C++)

1041. 困于环中的机器人(python)

1091. 二进制矩阵中的最短路径

1285. 找到连续区间的开始和结束数字(MySql)

1294. 不同国家的天气类型(MySql)

1303. 求团队人数(MySql)

1350. 院系无效的学生(MySql)

1355. 活动参与者(MySql)

1398. 购买了产品 A 和产品 B 却没有购买产品 C 的顾客(MySql)

1583. 统计不开心的朋友(python)

2490. 回环句(C++)


本文给的都是AI作答的结果,所有问答都是纯文本。

只给出AI给出的AC代码,不能AC的就算了。

有些题目,AI给不出c++代码,但是可以给出python代码。我默认都是用c++,c++无解答的才会尝试python。当然,还有少数题目是数据库题目,用的是MySql语言。

2. 两数相加(C++)

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

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

示例 1:


输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
 

提示:

每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* dummy = new ListNode(0); // 创建一个虚拟头结点
        ListNode* cur = dummy; // cur指向虚拟头结点
        int carry = 0; // 进位
        while (l1 || l2 || carry) { // 只要有一个链表不为空或者有进位,就继续循环
            int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + carry; // 计算当前位的和
            carry = sum / 10; // 计算进位
            cur->next = new ListNode(sum % 10); // 创建新结点存储当前位的值
            cur = cur->next; // cur指向新结点
            if (l1) l1 = l1->next; // l1指向下一个结点
            if (l2) l2 = l2->next; // l2指向下一个结点
        }
        return dummy->next; // 返回虚拟头结点的下一个结点
    }
};

4. 寻找两个正序数组的中位数(C++)


给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
 

提示:

nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        if (m > n) {
            return findMedianSortedArrays(nums2, nums1);
        }
        int left = 0, right = m, half_len = (m + n + 1) / 2;
        while (left <= right) {
            int i = (left + right) / 2;
            int j = half_len - i;
            if (i < m && nums2[j-1] > nums1[i]) {
                left = i + 1;
            } else if (i > 0 && nums1[i-1] > nums2[j]) {
                right = i - 1;
            } else {
                int max_left = 0;
                if (i == 0) {
                    max_left = nums2[j-1];
                } else if (j == 0) {
                    max_left = nums1[i-1];
                } else {
                    max_left = max(nums1[i-1], nums2[j-1]);
                }
                if ((m + n) % 2 == 1) {
                    return max_left;
                }
                int min_right = 0;
                if (i == m) {
                    min_right = nums2[j];
                } else if (j == n) {
                    min_right = nums1[i];
                } else {
                    min_right = min(nums1[i], nums2[j]);
                }
                return (max_left + min_right) / 2.0;
            }
        }
        return 0.0;
    }
};

5. 最长回文子串(python)

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:

输入:s = "cbbd"
输出:"bb"
 

提示:

1 <= s.length <= 1000
s 仅由数字和英文字母组成

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        n = len(s)
        dp = [[False] * n for _ in range(n)]
        ans = ""
        # 枚举子串的长度 l+1
        for l in range(n):
            # 枚举子串的起始位置 i,这样可以通过 j=i+l 得到子串的结束位置
            for i in range(n):
                j = i + l
                if j >= n:
                    break
                if l == 0:
                    dp[i][j] = True
                elif l == 1:
                    dp[i][j] = (s[i] == s[j])
                else:
                    dp[i][j] = (s[i] == s[j] and dp[i+1][j-1])
                if dp[i][j] and l + 1 > len(ans):
                    ans = s[i:j+1]
        return ans

6. N 字形变换(C++)

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);
 

示例 1:

输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"
示例 2:
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I
示例 3:

输入:s = "A", numRows = 1
输出:"A"
 

提示:

1 <= s.length <= 1000
s 由英文字母(小写和大写)、',' 和 '.' 组成
1 <= numRows <= 1000

class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1) {
            return s;
        }
        vector<vector<char>> matrix(numRows, vector<char>(s.size()));
        int row = 0, col = 0, flag = -1;
        for (char c : s) {
            matrix[row][col] = c;
            if (row == 0 || row == numRows - 1) {
                flag = -flag;
            }
            row += flag;
            col++;
        }
        string ans;
        for (int i = 0; i < numRows; i++) {
            for (int j = 0; j < s.size(); j++) {
                if (matrix[i][j] != 0) {
                    ans += matrix[i][j];
                }
            }
        }
        return ans;
    }
};

10. 正则表达式匹配(python)

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

 
示例 1:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。
示例 2:

输入:s = "aa", p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:

输入:s = "ab", p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
 

提示:

1 <= s.length <= 20
1 <= p.length <= 20
s 只包含从 a-z 的小写字母。
p 只包含从 a-z 的小写字母,以及字符 . 和 *。
保证每次出现字符 * 时,前面都匹配到有效的字符

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m, n = len(s), len(p)
        dp = [[False] * (n+1) for _ in range(m+1)]
        dp[0][0] = True
        for i in range(2, n+1):
            if p[i-1] == '*':
                dp[0][i] = dp[0][i-2]
        for i in range(1, m+1):
            for j in range(1, n+1):
                if s[i-1] == p[j-1] or p[j-1] == '.':
                    dp[i][j] = dp[i-1][j-1]
                elif p[j-1] == '*':
                    dp[i][j] = dp[i][j-2] or (dp[i-1][j] and (s[i-1] == p[j-2] or p[j-2] == '.'))
        return dp[m][n]

13. 罗马数字转整数(C++)


罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。

示例 1:

输入: s = "III"
输出: 3
示例 2:

输入: s = "IV"
输出: 4
示例 3:

输入: s = "IX"
输出: 9
示例 4:

输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
 

提示:

1 <= s.length <= 15
s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999] 内
题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics 。

class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> m = {
            {'I', 1},
            {'V', 5},
            {'X', 10},
            {'L', 50},
            {'C', 100},
            {'D', 500},
            {'M', 1000}
        };
        int res = 0;
        for (int i = 0; i < s.size(); i++) {
            if (i < s.size() - 1 && m[s[i]] < m[s[i+1]]) {
                res -= m[s[i]];
            } else {
                res += m[s[i]];
            }
        }
        return res;
    }
};

16. 最接近的三数之和(python)

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

示例 1:

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

示例 2:

输入:nums = [0,0,0], target = 1
输出:0

提示:

  • 3 <= nums.length <= 1000
  • -1000 <= nums[i] <= 1000
  • -104 <= target <= 104

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        n = len(nums)
        ans = float('inf')
        for i in range(n):
            left, right = i + 1, n - 1
            while left < right:
                sum = nums[i] + nums[left] + nums[right]
                if abs(sum - target) < abs(ans - target):
                    ans = sum
                if sum < target:
                    left += 1
                elif sum > target:
                    right -= 1
                else:
                    return target
        return ans

17. 电话号码的字母组合(python)

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:

输入:digits = ""
输出:[]
示例 3:

输入:digits = "2"
输出:["a","b","c"]
 

提示:

0 <= digits.length <= 4
digits[i] 是范围 ['2', '9'] 的一个数字。

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:
            return []
        mapping = {
            '2': 'abc',
            '3': 'def',
            '4': 'ghi',
            '5': 'jkl',
            '6': 'mno',
            '7': 'pqrs',
            '8': 'tuv',
            '9': 'wxyz'
        }
        res = []
        def backtrack(combination, next_digits):
            if not next_digits:
                res.append(combination)
            else:
                for letter in mapping[next_digits[0]]:
                    backtrack(combination + letter, next_digits[1:])
        backtrack('', digits)
        return res

24. 两两交换链表中的节点(C++)

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:


输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:

输入:head = []
输出:[]
示例 3:

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

提示:

链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        ListNode* p1 = dummy;
        ListNode* p2 = head;
        while (p2 && p2->next) {
            ListNode* next = p2->next->next;
            p1->next = p2->next;
            p2->next->next = p2;
            p2->next = next;
            p1 = p2;
            p2 = next;
        }
        return dummy->next;
    }
};

32. 最长有效括号(C++)

给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例 2:

输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"

示例 3:

输入:s = ""
输出:0

提示:

  • 0 <= s.length <= 3 * 104
  • s[i] 为 '(' 或 ')'
class Solution {
public:
    int longestValidParentheses(string s) {
        stack<int> stk;
        stk.push(-1);
        int maxLen = 0;
        for(int i = 0; i < s.size(); i++) {
            if(s[i] == '(') {
                stk.push(i);
            } else {
                stk.pop();
                if(stk.empty()) {
                    stk.push(i);
                } else {
                    maxLen = max(maxLen, i - stk.top());
                }
            }
        }
        return maxLen;
    }
};

38. 外观数列(python)

给定一个正整数 n ,输出外观数列的第 n 项。

「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。

你可以将其视作是由递归公式定义的数字字符串序列:

  • countAndSay(1) = "1"
  • countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。

前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221
第一项是数字 1 
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"

要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。

例如,数字字符串 "3322251" 的描述如下图:

示例 1:

输入:n = 1
输出:"1"
解释:这是一个基本样例。

示例 2:

输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = 读 "1" = 一 个 1 = "11"
countAndSay(3) = 读 "11" = 二 个 1 = "21"
countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"

提示:

  • 1 <= n <= 30
class Solution:
    def countAndSay(self, n: int) -> str:
        if n == 1:
            return '1'
        prev = self.countAndSay(n-1)
        res = ''
        i = 0
        while i < len(prev):
            count = 1
            while i < len(prev)-1 and prev[i] == prev[i+1]:
                count += 1
                i += 1
            res += str(count) + prev[i]
            i += 1
        return res

40. 组合总和 II(C++)

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。



示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]


提示:

1 <= candidates.length <= 100
1 <= candidates[i] <= 50
1 <= target <= 30

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<vector<int>> res;
        vector<int> path;
        sort(candidates.begin(), candidates.end()); // 对候选人编号集合进行排序
        backtrack(candidates, target, 0, path, res);
        return res;
    }

    void backtrack(vector<int>& candidates, int target, int start, vector<int>& path, vector<vector<int>>& res) {
        if (target == 0) { // 如果当前的数字和等于目标数,就将当前的组合加入结果集
            res.push_back(path);
            return;
        }
        for (int i = start; i < candidates.size() && candidates[i] <= target; i++) {
            if (i > start && candidates[i] == candidates[i-1]) continue; // 去重
            path.push_back(candidates[i]);
            backtrack(candidates, target-candidates[i], i+1, path, res); // 从当前数字的下一个位置开始继续回溯
            path.pop_back();
        }
    }
};

43. 字符串相乘(C++)

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

示例 1:

输入: num1 = "2", num2 = "3"
输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"
输出: "56088"

提示:

  • 1 <= num1.length, num2.length <= 200
  • num1 和 num2 只能由数字组成。
  • num1 和 num2 都不包含任何前导零,除了数字0本身。
class Solution {
public:
    string multiply(string num1, string num2) {
        int n1 = num1.size();
        int n2 = num2.size();
        vector<int> result(n1 + n2, 0);
        for (int i = n1 - 1; i >= 0; i--) {
            for (int j = n2 - 1; j >= 0; j--) {
                int mul = (num1[i] - '0') * (num2[j] - '0');
                int p1 = i + j, p2 = i + j + 1;
                int sum = mul + result[p2];
                result[p1] += sum / 10;
                result[p2] = sum % 10;
            }
        }
        string ans = "";
        for (int num : result) {
            if (!(ans.empty() && num == 0)) {
                ans += to_string(num);
            }
        }
        return ans.empty() ? "0" : ans;
    }
};

44. 通配符匹配(C++)

给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 '?' 和 '*' 匹配规则的通配符匹配:

  • '?' 可以匹配任何单个字符。
  • '*' 可以匹配任意字符序列(包括空字符序列)。

判定匹配成功的充要条件是:字符模式必须能够 完全匹配 输入字符串(而不是部分匹配)。

示例 1:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:s = "aa", p = "*"
输出:true
解释:'*' 可以匹配任意字符串。

示例 3:

输入:s = "cb", p = "?a"
输出:false
解释:'?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。

提示:

  • 0 <= s.length, p.length <= 2000
  • s 仅由小写英文字母组成
  • p 仅由小写英文字母、'?' 或 '*' 组成
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m, n = len(s), len(p)
        dp = [[False] * (n+1) for _ in range(m+1)]
        dp[0][0] = True
        for j in range(1, n+1):
            if p[j-1] == '*':
                dp[0][j] = dp[0][j-1]
        for i in range(1, m+1):
            for j in range(1, n+1):
                if p[j-1] == s[i-1] or p[j-1] == '?':
                    dp[i][j] = dp[i-1][j-1]
                elif p[j-1] == '*':
                    dp[i][j] = dp[i][j-1] or dp[i-1][j]
        return dp[m][n]

48. 旋转图像(C++)

给定一个 × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

示例 2:

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

提示:

  • n == matrix.length == matrix[i].length
  • 1 <= n <= 20
  • -1000 <= matrix[i][j] <= 1000
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        // 矩阵转置
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                swap(matrix[i][j], matrix[j][i]);
            }
        }
        // 每行翻转
        for (int i = 0; i < n; i++) {
            reverse(matrix[i].begin(), matrix[i].end());
        }
    }
};

57. 插入区间(C++)

给你一个 无重叠的 ,按照区间起始端点排序的区间列表。

在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

示例 1:

输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
输出:[[1,5],[6,9]]

示例 2:

输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间 [4,8][3,5],[6,7],[8,10] 重叠。

示例 3:

输入:intervals = [], newInterval = [5,7]
输出:[[5,7]]

示例 4:

输入:intervals = [[1,5]], newInterval = [2,3]
输出:[[1,5]]

示例 5:

输入:intervals = [[1,5]], newInterval = [2,7]
输出:[[1,7]]

提示:

  • 0 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= intervals[i][0] <= intervals[i][1] <= 105
  • intervals 根据 intervals[i][0] 按 升序 排列
  • newInterval.length == 2
  • 0 <= newInterval[0] <= newInterval[1] <= 105
class Solution {
public:
    vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
        vector<vector<int>> res;
        int n = intervals.size();
        int i = 0;
        // 找到新区间左侧不重叠的区间
        while (i < n && intervals[i][1] < newInterval[0]) {
            res.push_back(intervals[i++]);
        }
        // 合并重叠的区间
        while (i < n && intervals[i][0] <= newInterval[1]) {
            newInterval[0] = min(newInterval[0], intervals[i][0]);
            newInterval[1] = max(newInterval[1], intervals[i][1]);
            i++;
        }
        res.push_back(newInterval);
        // 将右侧不重叠的区间加入结果
        while (i < n) {
            res.push_back(intervals[i++]);
        }
        return res;
    }
};

65. 有效数字(C++)

有效数字(按顺序)可以分成以下几个部分:

  1. 一个 小数 或者 整数
  2. (可选)一个 'e' 或 'E' ,后面跟着一个 整数

小数(按顺序)可以分成以下几个部分:

  1. (可选)一个符号字符('+' 或 '-'
  2. 下述格式之一:
    1. 至少一位数字,后面跟着一个点 '.'
    2. 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
    3. 一个点 '.' ,后面跟着至少一位数字

整数(按顺序)可以分成以下几个部分:

  1. (可选)一个符号字符('+' 或 '-'
  2. 至少一位数字

部分有效数字列举如下:["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]

部分无效数字列举如下:["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]

给你一个字符串 s ,如果 s 是一个 有效数字 ,请返回 true 。

示例 1:

输入:s = "0"
输出:true

示例 2:

输入:s = "e"
输出:false

示例 3:

输入:s = "."
输出:false

提示:

  • 1 <= s.length <= 20
  • s 仅含英文字母(大写和小写),数字(0-9),加号 '+' ,减号 '-' ,或者点 '.' 。
class Solution {
public:
    bool isNumber(string s) {
        int n = s.size();
        bool hasE = false, hasDot = false, hasNum = false, hasNumAfterE = true;
        for (int i = 0; i < n; i++) {
            if (s[i] == ' ') {
                if (i < n - 1 && s[i + 1] != ' ' && (hasNum || hasDot || hasE)) {
                    return false;
                }
            } else if (s[i] == '+' || s[i] == '-') {
                if (i > 0 && s[i - 1] != 'e' && s[i - 1] != 'E') {
                    return false;
                }
            } else if (s[i] >= '0' && s[i] <= '9') {
                hasNum = true;
                if (hasE) {
                    hasNumAfterE = true;
                }
            } else if (s[i] == '.') {
                if (hasE || hasDot) {
                    return false;
                }
                hasDot = true;
            } else if (s[i] == 'e' || s[i] == 'E') {
                if (hasE || !hasNum) {
                    return false;
                }
                hasE = true;
                hasNumAfterE = false;
            } else {
                return false;
            }
        }
        return hasNum && hasNumAfterE;
    }
};

68. 文本左右对齐(python)

给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。

你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。

要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。

文本的最后一行应为左对齐,且单词之间不插入额外的空格。

注意:

  • 单词是指由非空格字符组成的字符序列。
  • 每个单词的长度大于 0,小于等于 maxWidth
  • 输入单词数组 words 至少包含一个单词。

示例 1:

输入: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
输出:
[
   "This    is    an",
   "example  of text",
   "justification.  "
]

示例 2:

输入:words = ["What","must","be","acknowledgment","shall","be"], maxWidth = 16
输出:
[
  "What   must   be",
  "acknowledgment  ",
  "shall be        "
]
解释: 注意最后一行的格式应为 "shall be    " 而不是 "shall     be",
     因为最后一行应为左对齐,而不是左右两端对齐。       
     第二行同样为左对齐,这是因为这行只包含一个单词。

示例 3:

输入:words = ["Science","is","what","we","understand","well","enough","to","explain","to","a","computer.","Art","is","everything","else","we","do"],maxWidth = 20
输出:
[
  "Science  is  what we",
  "understand      well",
  "enough to explain to",
  "a  computer.  Art is",
  "everything  else  we",
  "do                  "
]

提示:

  • 1 <= words.length <= 300
  • 1 <= words[i].length <= 20
  • words[i] 由小写英文字母和符号组成
  • 1 <= maxWidth <= 100
  • words[i].length <= maxWidth
class Solution:
    def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
        n = len(words)
        res = []
        i = 0
        while i < n:
            # 每行的第一个单词
            j = i + 1
            line_len = len(words[i])
            while j < n and line_len + len(words[j]) + j - i <= maxWidth:
                line_len += len(words[j])
                j += 1
            # 计算空格数量和额外空格数量
            space_count = j - i - 1
            if space_count == 0 or j == n:
                # 只有一个单词或者是最后一行
                line = ' '.join(words[i:j])
                line += ' ' * (maxWidth - len(line))
            else:
                # 计算每个空格的数量和额外空格的数量
                space_len = (maxWidth - line_len) // space_count
                extra_space = (maxWidth - line_len) % space_count
                line = words[i]
                for k in range(i + 1, j):
                    if extra_space > 0:
                        line += ' ' * (space_len + 1)
                        extra_space -= 1
                    else:
                        line += ' ' * space_len
                    line += words[k]
            res.append(line)
            i = j
        return res

71. 简化路径(python)

给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 '/' 开头),请你将其转化为更加简洁的规范路径。

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//')都被视为单个斜杠 '/' 。 对于此问题,任何其他格式的点(例如,'...')均被视为文件/目录名称。

请注意,返回的 规范路径 必须遵循下述格式:

  • 始终以斜杠 '/' 开头。
  • 两个目录名之间必须只有一个斜杠 '/' 。
  • 最后一个目录名(如果存在)不能 以 '/' 结尾。
  • 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 '.' 或 '..')。

返回简化后得到的 规范路径 。

示例 1:

输入:path = "/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。 

示例 2:

输入:path = "/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根目录是你可以到达的最高级。

示例 3:

输入:path = "/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。

示例 4:

输入:path = "/a/./b/../../c/"
输出:"/c"

提示:

  • 1 <= path.length <= 3000
  • path 由英文字母,数字,'.''/' 或 '_' 组成。
  • path 是一个有效的 Unix 风格绝对路径。
class Solution(object):
    def simplifyPath(self, path):
        """
        :type path: str
        :rtype: str
        """
        stack = []
        # 将路径按照 '/' 分割
        path_list = path.split('/')
        for item in path_list:
            # 如果是空字符串或者当前目录'.', 则直接跳过
            if item == '' or item == '.':
                continue
            # 如果是上级目录'..', 则弹出栈顶元素
            elif item == '..':
                if stack:
                    stack.pop()
            else:
                stack.append(item)
        # 将栈中元素用 '/' 拼接起来
        res = '/' + '/'.join(stack)
        return res

97. 交错字符串(python)

给定三个字符串 s1s2s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。

两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 

子字符串

  • s = s1 + s2 + ... + sn
  • t = t1 + t2 + ... + tm
  • |n - m| <= 1
  • 交错 是 s1 + t1 + s2 + t2 + s3 + t3 + ... 或者 t1 + s1 + t2 + s2 + t3 + s3 + ...

注意:a + b 意味着字符串 a 和 b 连接。

示例 1:

输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出:true

示例 2:

输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出:false

示例 3:

输入:s1 = "", s2 = "", s3 = ""
输出:true

提示:

  • 0 <= s1.length, s2.length <= 100
  • 0 <= s3.length <= 200
  • s1s2、和 s3 都由小写英文字母组成

进阶:您能否仅使用 O(s2.length) 额外的内存空间来解决它?

class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        if len(s1) + len(s2) != len(s3):
            return False
        
        dp = [[False] * (len(s2)+1) for _ in range(len(s1)+1)]
        dp[0][0] = True
        
        for i in range(1, len(s1)+1):
            dp[i][0] = dp[i-1][0] and s1[i-1] == s3[i-1]
        
        for j in range(1, len(s2)+1):
            dp[0][j] = dp[0][j-1] and s2[j-1] == s3[j-1]
        
        for i in range(1, len(s1)+1):
            for j in range(1, len(s2)+1):
                dp[i][j] = (dp[i-1][j] and s1[i-1] == s3[i+j-1]) or (dp[i][j-1] and s2[j-1] == s3[i+j-1])
        
        return dp[len(s1)][len(s2)]

115. 不同的子序列(C++)

给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数,结果需要对 109 + 7 取模。

示例 1:

输入:s = "rabbbit", t = "rabbit"
输出3
解释:
如下所示, 有 3 种可以从 s 中得到 "rabbit" 的方案rabbbit
rabbbit
rabbbit

示例 2:

输入:s = "babgbag", t = "bag"
输出5
解释:
如下所示, 有 5 种可以从 s 中得到 "bag" 的方案babgbag
babgbag
babgbag
babgbag
babgbag

提示:

  • 1 <= s.length, t.length <= 1000
  • s 和 t 由英文字母组成
class Solution {
public:
    int numDistinct(string s, string t) {
        int n = s.size(), m = t.size();
        vector<vector<long long>> dp(n+1, vector<long long>(m+1, 0));
        for (int i = 0; i <= n; i++) {
            dp[i][0] = 1;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (s[i-1] == t[j-1]) {
                    dp[i][j] = dp[i-1][j] + dp[i-1][j-1];
                } else {
                    dp[i][j] = dp[i-1][j];
                }
                dp[i][j] %= 1000000007;
            }
        }
        return dp[n][m];
    }
};

127. 单词接龙(C++)

字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk

  • 每一对相邻的单词只差一个字母。
  •  对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。
  • sk == endWord

给你两个单词 beginWord 和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。

示例 1:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:5
解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。

示例 2:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:0
解释:endWord "cog" 不在字典中,所以无法进行转换。

提示:

  • 1 <= beginWord.length <= 10
  • endWord.length == beginWord.length
  • 1 <= wordList.length <= 5000
  • wordList[i].length == beginWord.length
  • beginWordendWord 和 wordList[i] 由小写英文字母组成
  • beginWord != endWord
  • wordList 中的所有字符串 互不相同
class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string> dict(wordList.begin(), wordList.end());
        if (!dict.count(endWord)) {
            return 0;
        }
        unordered_set<string> q1{beginWord};
        unordered_set<string> q2{endWord};
        unordered_set<string> visited;
        int step = 0;
        while (!q1.empty() && !q2.empty()) {
            ++step;
            if (q1.size() > q2.size()) {
                swap(q1, q2);
            }
            unordered_set<string> q;
            for (const auto& w : q1) {
                string s = w;
                for (size_t i = 0; i < s.size(); ++i) {
                    const char ch = s[i];
                    for (char j = 'a'; j <= 'z'; ++j) {
                        if (j == ch) {
                            continue;
                        }
                        s[i] = j;
                        if (q2.count(s)) {
                            return step + 1;
                        }
                        if (!visited.count(s) && dict.count(s)) {
                            visited.insert(s);
                            q.insert(s);
                        }
                    }
                    s[i] = ch;
                }
            }
            swap(q, q1);
        }
        return 0;
    }
};

131. 分割回文串(python)

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 

回文串

 。返回 s 所有可能的分割方案。

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

输入:s = "a"
输出:[["a"]]

提示:

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成
class Solution:
    def partition(self, s: str) -> List[List[str]]:
        def partition_helper(start: int, path: List[str], result: List[List[str]]):
            if start == len(s):
                result.append(path[:])
                return
            
            for end in range(start+1, len(s)+1):
                if s[start:end] == s[start:end][::-1]:
                    path.append(s[start:end])
                    partition_helper(end, path, result)
                    path.pop()
        
        result = []
        partition_helper(0, [], result)
        return result

132. 分割回文串 II

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是

回文串

返回符合要求的 最少分割次数 。

示例 1:

输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

示例 2:

输入:s = "a"
输出:0

示例 3:

输入:s = "ab"
输出:1

提示:

  • 1 <= s.length <= 2000
  • s 仅由小写英文字母组成
class Solution:
    def minCut(self, s: str) -> int:
        n = len(s)
        dp = [i-1 for i in range(n+1)]
        for i in range(1, n+1):
            for j in range(i):
                if s[j:i] == s[j:i][::-1]:
                    dp[i] = min(dp[i], dp[j]+1)
        return dp[-1]

166. 分数到小数(C++)

给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数 。

如果小数部分为循环小数,则将循环的部分括在括号内。

如果存在多个答案,只需返回 任意一个 。

对于所有给定的输入,保证 答案字符串的长度小于 104 。

示例 1:

输入:numerator = 1, denominator = 2
输出:"0.5"

示例 2:

输入:numerator = 2, denominator = 1
输出:"2"

示例 3:

输入:numerator = 4, denominator = 333
输出:"0.(012)"

提示:

  • -231 <= numerator, denominator <= 231 - 1
  • denominator != 0
class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        long long num = numerator, den = denominator; // 转化为 long long 防止溢出
        string res = "";
        if (num * den < 0) res += "-"; // 判断正负号
        num = abs(num), den = abs(den);
        res += to_string(num / den); // 计算整数部分
        long long rem = num % den;
        if (rem == 0) return res; // 如果小数部分为 0,则直接返回整数部分
        res += ".";
        unordered_map<long long, int> mp; // 用哈希表存储余数
        while (rem != 0) {
            if (mp.count(rem) > 0) { // 如果出现了重复的余数,则说明出现了循环小数
                res.insert(mp[rem], "(");
                res += ")";
                break;
            }
            mp[rem] = res.size(); // 记录余数对应的位置
            rem *= 10;
            res += to_string(rem / den);
            rem %= den;
        }
        return res;
    }
};

168. Excel表列名称(C++)

给你一个整数 columnNumber ,返回它在 Excel 表中相对应的列名称。

例如:

A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28 
...

示例 1:

输入:columnNumber = 1
输出:"A"

示例 2:

输入:columnNumber = 28
输出:"AB"

示例 3:

输入:columnNumber = 701
输出:"ZY"

示例 4:

输入:columnNumber = 2147483647
输出:"FXSHRXW"

提示:

  • 1 <= columnNumber <= 231 - 1
class Solution {
public:
    string convertToTitle(int columnNumber) {
        if (columnNumber <= 0) {
            return "";
        }
        int remainder = (columnNumber - 1) % 26;
        int quotient = (columnNumber - 1) / 26;
        return convertToTitle(quotient) + char('A' + remainder);
    }
};

171. Excel 表列序号

给你一个字符串 columnTitle ,表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。

例如:

A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28 
...

示例 1:

输入: columnTitle = "A"
输出: 1

示例 2:

输入: columnTitle = "AB"
输出: 28

示例 3:

输入: columnTitle = "ZY"
输出: 701

提示:

  • 1 <= columnTitle.length <= 7
  • columnTitle 仅由大写英文组成
  • columnTitle 在范围 ["A", "FXSHRXW"] 内
class Solution {
public:
    int titleToNumber(string columnTitle) {
        int res = 0;
        for (auto c : columnTitle) {
            res = res * 26 + (c - 'A' + 1);
        }
        return res;
    }
};

224. 基本计算器(python)

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

 

示例 1:

输入:s = "1 + 1"
输出:2

示例 2:

输入:s = " 2-1 + 2 "
输出:3

示例 3:

输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23

 

提示:

  • 1 <= s.length <= 3 * 105
  • s 由数字、'+''-''('')'、和 ' ' 组成
  • s 表示一个有效的表达式
  • '+' 不能用作一元运算(例如, "+1" 和 "+(2 + 3)" 无效)
  • '-' 可以用作一元运算(即 "-1" 和 "-(2 + 3)" 是有效的)
  • 输入中不存在两个连续的操作符
  • 每个数字和运行的计算将适合于一个有符号的 32位 整数
class Solution:
    def calculate(self, s: str) -> int:
        stack = []
        num = 0
        sign = 1
        res = 0
        for c in s:
            if c.isdigit():
                num = num * 10 + int(c)
            elif c == '+':
                res += sign * num
                num = 0
                sign = 1
            elif c == '-':
                res += sign * num
                num = 0
                sign = -1
            elif c == '(':
                stack.append(res)
                stack.append(sign)
                res = 0
                sign = 1
            elif c == ')':
                res += sign * num
                num = 0
                res *= stack.pop()
                res += stack.pop()
        if num:
            res += sign * num
        return res

227. 基本计算器 II(C++)

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

示例 1:

输入:s = "3+2*2"
输出:7

示例 2:

输入:s = " 3/2 "
输出:1

示例 3:

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

提示:

  • 1 <= s.length <= 3 * 105
  • s 由整数和算符 ('+', '-', '*', '/') 组成,中间由一些空格隔开
  • s 表示一个 有效表达式
  • 表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1] 内
  • 题目数据保证答案是一个 32-bit 整数
class Solution {
public:
    int calculate(string s) {
        stack<int> stk;
        int num = 0;
        char sign = '+';
        for (int i = 0; i < s.size(); i++) {
            char c = s[i];
            if (isdigit(c)) {
                num = num * 10 + (c - '0');
            }
            if (!isdigit(c) && c != ' ' || i == s.size() - 1) {
                if (sign == '+') {
                    stk.push(num);
                } else if (sign == '-') {
                    stk.push(-num);
                } else if (sign == '*') {
                    int top = stk.top();
                    stk.pop();
                    stk.push(top * num);
                } else if (sign == '/') {
                    int top = stk.top();
                    stk.pop();
                    stk.push(top / num);
                }
                sign = c;
                num = 0;
            }
        }
        int res = 0;
        while (!stk.empty()) {
            res += stk.top();
            stk.pop();
        }
        return res;
    }
};

241. 为运算表达式设计优先级(python)

给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。

生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 104 。

示例 1:

输入:expression = "2-1-1"
输出:[0,2]
解释:
((2-1)-1) = 0 
(2-(1-1)) = 2

示例 2:

输入:expression = "2*3-4*5"
输出:[-34,-14,-10,-10,10]
解释:
(2*(3-(4*5))) = -34 
((2*3)-(4*5)) = -14 
((2*(3-4))*5) = -10 
(2*((3-4)*5)) = -10 
(((2*3)-4)*5) = 10

提示:

  • 1 <= expression.length <= 20
  • expression 由数字和算符 '+''-' 和 '*' 组成。
  • 输入表达式中的所有整数值在范围 [0, 99] 
class Solution:
    def diffWaysToCompute(self, expression: str) -> List[int]:
        # 如果表达式中只有一个数字,直接返回该数字
        if expression.isdigit():
            return [int(expression)]
        
        res = []
        # 遍历整个表达式
        for i in range(len(expression)):
            # 如果遇到运算符
            if expression[i] in ['+', '-', '*']:
                # 将表达式分成左右两部分
                left = expression[:i]
                right = expression[i+1:]
                # 对左右两部分进行递归计算
                left_res = self.diffWaysToCompute(left)
                right_res = self.diffWaysToCompute(right)
                # 将左右两部分的结果进行组合
                for x in left_res:
                    for y in right_res:
                        if expression[i] == '+':
                            res.append(x+y)
                        elif expression[i] == '-':
                            res.append(x-y)
                        elif expression[i] == '*':
                            res.append(x*y)
        
        return res

288. 单词的唯一缩写(C++)

单词的 缩写 需要遵循 <起始字母><中间字母数><结尾字母> 这样的格式。如果单词只有两个字符,那么它就是它自身的 缩写 。

以下是一些单词缩写的范例:

  • dog --> d1g 因为第一个字母 'd' 和最后一个字母 'g' 之间有 1 个字母
  • internationalization --> i18n 因为第一个字母 'i' 和最后一个字母 'n' 之间有 18 个字母
  • it --> it 单词只有两个字符,它就是它自身的 缩写

实现 ValidWordAbbr 类:

  • ValidWordAbbr(String[] dictionary) 使用单词字典 dictionary 初始化对象
  • boolean isUnique(string word) 如果满足下述任意一个条件,返回 true ;否则,返回 false :
    • 字典 dictionary 中没有任何其他单词的 缩写 与该单词 word 的 缩写 相同。
    • 字典 dictionary 中的所有 缩写 与该单词 word 的 缩写 相同的单词都与 word 相同 。

示例:

输入
["ValidWordAbbr", "isUnique", "isUnique", "isUnique", "isUnique", "isUnique"]
[[["deer", "door", "cake", "card"]], ["dear"], ["cart"], ["cane"], ["make"], ["cake"]]
输出
[null, false, true, false, true, true]

解释
ValidWordAbbr validWordAbbr = new ValidWordAbbr(["deer", "door", "cake", "card"]);
validWordAbbr.isUnique("dear"); // 返回 false,字典中的 "deer" 与输入 "dear" 的缩写都是 "d2r",但这两个单词不相同
validWordAbbr.isUnique("cart"); // 返回 true,字典中不存在缩写为 "c2t" 的单词
validWordAbbr.isUnique("cane"); // 返回 false,字典中的 "cake" 与输入 "cane" 的缩写都是 "c2e",但这两个单词不相同
validWordAbbr.isUnique("make"); // 返回 true,字典中不存在缩写为 "m2e" 的单词
validWordAbbr.isUnique("cake"); // 返回 true,因为 "cake" 已经存在于字典中,并且字典中没有其他缩写为 "c2e" 的单词

提示:

  • 1 <= dictionary.length <= 3 * 104
  • 1 <= dictionary[i].length <= 20
  • dictionary[i] 由小写英文字母组成
  • 1 <= word <= 20
  • word 由小写英文字母组成
  • 最多调用 5000 次 isUnique

class ValidWordAbbr {
public:
    ValidWordAbbr(std::vector<std::string>& dictionary) {
        for (const auto& word : dictionary) {
            std::string abbr = getAbbreviation(word);
            words[abbr].push_back(word);
        }
    }
    
    bool isUnique(const std::string& word) {
        std::string abbr = getAbbreviation(word);
        auto it = words.find(abbr);
        if (it == words.end()) {
            return true;  // 缩写未出现过,肯定唯一
        } else {
            const std::vector<std::string>& list = it->second;
            // 新增逻辑:检查列表中所有单词是否都与输入的单词相同
            bool allSame = true;
            for (const std::string& w : list) {
                if (w != word) {
                    allSame = false;
                    break;
                }
            }
            return allSame;
        }
    }

private:
    std::unordered_map<std::string, std::vector<std::string>> words;

    std::string getAbbreviation(const std::string& word) {
        if (word.length() <= 2) {
            return word;
        }
        return word.front() + std::to_string(word.length() - 2) + word.back();
    }
};

320. 列举单词的全部缩写(C++)

单词的 广义缩写词 可以通过下述步骤构造:先取任意数量的 不重叠、不相邻 的

子字符串

,再用它们各自的长度进行替换。

  • 例如,"abcde" 可以缩写为:
    • "a3e""bcd" 变为 "3" )
    • "1bcd1""a" 和 "e" 都变为 "1"
    • "5" ("abcde" 变为 "5")
    • "abcde" (没有子字符串被代替)
  • 然而,这些缩写是 无效的 :
    • "23""ab" 变为 "2" ,"cde" 变为 "3" )是无效的,因为被选择的字符串是相邻的
    • "22de" ("ab" 变为 "2" , "bc" 变为 "2")  是无效的,因为被选择的字符串是重叠的

给你一个字符串 word ,返回 一个由 word 的所有可能 广义缩写词 组成的列表 。按 任意顺序 返回答案。

示例 1:

输入:word = "word"
输出:["4","3d","2r1","2rd","1o2","1o1d","1or1","1ord","w3","w2d","w1r1","w1rd","wo2","wo1d","wor1","word"]

示例 2:

输入:word = "a"
输出:["1","a"]

提示:

  • 1 <= word.length <= 15
  • word 仅由小写英文字母组成
class Solution {
public:
    vector<string> generateAbbreviations(string word) {
        vector<string> res;
        string cur; // 当前构造的字符串
        dfs(word, 0, 0, cur, res); // 从第一个字符开始构造
        sort(res.begin(), res.end());
        res.erase(std::unique(res.begin(), res.end()), res.end());
        return res;
    }

    void dfs(const string& word, int start, int flag, string& cur, vector<string>& res) {
        if (start == word.size()) {
            res.push_back(cur);
            return;
        }

        // 枚举当前子字符串的长度
        for (int len = 1; len <= word.size() - start; ++len) {
            string sub_word = word.substr(start, len);
            int len_len = to_string(len).size(); // 子字符串长度的长度

            if (flag == 0) {
                // 放入数字
                cur += to_string(len);
                dfs(word, start + len, 1, cur, res); // 下一步放入子字符串
                cur.erase(cur.size() - len_len, len_len); // 回溯
            }

            // 放入子字符串
            cur += sub_word;
            dfs(word, start + len, 0, cur, res); // 下一步放入数字
            cur.erase(cur.size() - len, len); // 回溯
        }
    }
};

415. 字符串相加(C++)

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。

你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。

示例 1:

输入:num1 = "11", num2 = "123"
输出:"134"
示例 2:

输入:num1 = "456", num2 = "77"
输出:"533"
示例 3:

输入:num1 = "0", num2 = "0"
输出:"0"
 

提示:

1 <= num1.length, num2.length <= 104
num1 和num2 都只包含数字 0-9
num1 和num2 都不包含任何前导零

class Solution {
public:
    string addStrings(string num1, string num2) {
        string res = "";
        int carry = 0;
        int i = num1.size() - 1, j = num2.size() - 1;
        while (i >= 0 || j >= 0 || carry > 0) {
            int sum = carry;
            if (i >= 0) sum += num1[i--] - '0';
            if (j >= 0) sum += num2[j--] - '0';
            carry = sum / 10;
            sum %= 10;
            res = to_string(sum) + res;
        }
        return res;
    }
};

527. 单词缩写(C++)

给你一个字符串数组 words ,该数组由 互不相同 的若干字符串组成,请你找出并返回每个单词的 最小缩写 。

生成缩写的规则如下

  1. 初始缩写由起始字母+省略字母的数量+结尾字母组成。
  2. 若存在冲突,亦即多于一个单词有同样的缩写,则使用更长的前缀代替首字母,直到从单词到缩写的映射唯一。换而言之,最终的缩写必须只能映射到一个单词。
  3. 若缩写并不比原单词更短,则保留原样。

示例 1:

输入: words = ["like", "god", "internal", "me", "internet", "interval", "intension", "face", "intrusion"]
输出: ["l2e","god","internal","me","i6t","interval","inte4n","f2e","intr4n"]

示例 2:

输入:words = ["aa","aaa"]
输出:["aa","aaa"]

提示:

  • 1 <= words.length <= 400
  • 2 <= words[i].length <= 400
  • words[i] 由小写英文字母组成
  • words 中的所有字符串 互不相同
class Solution {
public:
    vector<string> wordsAbbreviation(vector<string>& words) {
        int n = words.size();
        vector<string> abbr(n);
        vector<int> prefixLengths(n, 1); // 初始化每个单词的前缀长度为1(即首字母)

        // 当存在冲突时,需要不断增长前缀长度
        for (int i = 0; i < n; ++i) {
            while (hasConflict(words, i, prefixLengths[i])) {
                ++prefixLengths[i]; // 增加当前单词的前缀长度
            }
            abbr[i] = createAbbreviation(words[i], prefixLengths[i]);
        }

        return abbr;
    }

private:
    // 检查使用当前前缀长度生成的缩写是否会导致冲突
    bool hasConflict(const vector<string>& words, int index, int prefixLength) {
        string abbr = createAbbreviation(words[index], prefixLength);
        for (int i = 0; i < words.size(); ++i) {
            if (i != index && words[i].substr(0, prefixLength) == words[index].substr(0, prefixLength) &&
                words[i].size() >= prefixLength + 2 && // 确保有足够的字符用于省略计数和尾字母
                words[i].back() == words[index].back() && 
                createAbbreviation(words[i], prefixLength) == abbr) {
                return true; // 发现冲突
            }
        }
        return false;
    }

    // 根据给定的前缀长度创建单词的缩写
    string createAbbreviation(const string& word, int prefixLength) {
        int suffixLength = word.size() - prefixLength;
        if (suffixLength <= 2 || prefixLength >= word.size() - 2) {
            return word; // 缩写不比原词短或无法形成有效缩写,直接返回原词
        }
        return word.substr(0, prefixLength) + to_string(suffixLength-1) + word.back();
    }
};

534. 游戏玩法分析 III(MySql)

表:Activity

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| player_id    | int     |
| device_id    | int     |
| event_date   | date    |
| games_played | int     |
+--------------+---------+
(player_id,event_date)是此表的主键(具有唯一值的列)。
这张表显示了某些游戏的玩家的活动情况。
每一行是一个玩家的记录,他在某一天使用某个设备注销之前登录并玩了很多游戏(可能是 0 )。

编写一个解决方案,同时报告每组玩家和日期,以及玩家到 目前为止 玩了多少游戏。也就是说,玩家在该日期之前所玩的游戏总数。详细情况请查看示例。

以 任意顺序 返回结果表。

结果格式如下所示。

示例 1:

输入:
Activity table:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-05-02 | 6            |
| 1         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-02 | 0            |
| 3         | 4         | 2018-07-03 | 5            |
+-----------+-----------+------------+--------------+
输出:
+-----------+------------+---------------------+
| player_id | event_date | games_played_so_far |
+-----------+------------+---------------------+
| 1         | 2016-03-01 | 5                   |
| 1         | 2016-05-02 | 11                  |
| 1         | 2017-06-25 | 12                  |
| 3         | 2016-03-02 | 0                   |
| 3         | 2018-07-03 | 5                   |
+-----------+------------+---------------------+
解释:
对于 ID 为 1 的玩家,2016-05-02 共玩了 5+6=11 个游戏,2017-06-25 共玩了 5+6+1=12 个游戏。
对于 ID 为 3 的玩家,2018-07-03 共玩了 0+5=5 个游戏。
请注意,对于每个玩家,我们只关心玩家的登录日期。
SELECT
    player_id,
    event_date,
    SUM(games_played) OVER (PARTITION BY player_id ORDER BY event_date) AS games_played_so_far
FROM Activity;

548. 将数组分割成和相等的子数组(C++)

给定一个有 n 个整数的数组 nums ,如果能找到满足以下条件的三元组  (i, j, k)  则返回 true :

  1. 0 < i, i + 1 < j, j + 1 < k < n - 1
  2. 子数组 (0, i - 1) , (i + 1, j - 1) , (j + 1, k - 1) , (k + 1, n - 1) 的和应该相等。

这里我们定义子数组 (l, r) 表示原数组从索引为 l 的元素开始至索引为 r 的元素。

示例 1: 

输入: nums = [1,2,1,2,1,2,1]
输出: True
解释:
i = 1, j = 3, k = 5. 
sum(0, i - 1) = sum(0, 0) = 1
sum(i + 1, j - 1) = sum(2, 2) = 1
sum(j + 1, k - 1) = sum(4, 4) = 1
sum(k + 1, n - 1) = sum(6, 6) = 1

示例 2:

输入: nums = [1,2,1,2,1,2,1,2]
输出: false

提示:

  • n == nums.length
  • 1 <= n <= 2000
  • -106 <= nums[i] <= 106
class Solution {
public:
    bool splitArray(vector<int>& nums) {
        int n = nums.size();
        if (n < 7) {
            return false; // 数组长度小于 7,不可能满足条件
        }

        vector<int> prefixSum(n); // 前缀和数组
        prefixSum[0] = nums[0];
        for (int i = 1; i < n; ++i) {
            prefixSum[i] = prefixSum[i - 1] + nums[i];
        }

        for (int j = 3; j < n - 3; ++j) {
            unordered_set<int> seen; // 哈希表存储子数组和
            for (int i = 1; i < j - 1; ++i) {
                int sum1 = prefixSum[i - 1]; // 子数组 (0, i - 1) 的和
                int sum2 = prefixSum[j - 1] - prefixSum[i]; // 子数组 (i + 1, j - 1) 的和
                if (sum1 == sum2) {
                    seen.insert(sum1);
                }
            }

            for (int k = j + 2; k < n - 1; ++k) {
                int sum3 = prefixSum[k - 1] - prefixSum[j]; // 子数组 (j + 1, k - 1) 的和
                int sum4 = prefixSum[n - 1] - prefixSum[k]; // 子数组 (k + 1, n - 1) 的和
                if (sum3 == sum4 && seen.count(sum3)) {
                    return true;
                }
            }
        }

        return false;
    }
};

573. 松鼠模拟(C++)

给你两个整数 height 和 width ,代表一个大小为 height x width 的花园。你还得到了以下信息:

  • 一个数组 tree ,其中 tree = [treer, treec] 是花园中树的位置,
  • 一个数组 squirrel ,其中 squirrel = [squirrelr, squirrelc] 是花园中松鼠的位置,
  • 一个数组 nuts ,其中 nuts[i] = [nutir, nutic] 是花园中第 ith 个坚果的位置。

松鼠一次最多只能携带一个坚果,并且能够向上、下、左、右四个方向移动到相邻的单元格。

返回松鼠收集所有坚果并逐一放在树下的 最小距离 。

距离 是指移动的次数。

示例 1:

输入:height = 5, width = 7, tree = [2,2], squirrel = [4,4], nuts = [[3,0], [2,5]]
输出:12
解释:为实现最小的距离,松鼠应该先摘 [2, 5] 位置的坚果。

示例 2:

输入:height = 1, width = 3, tree = [0,1], squirrel = [0,0], nuts = [[0,2]]
输出:3

提示:

  • 1 <= height, width <= 100
  • tree.length == 2
  • squirrel.length == 2
  • 1 <= nuts.length <= 5000
  • nuts[i].length == 2
  • 0 <= treer, squirrelr, nutir <= height
  • 0 <= treec, squirrelc, nutic <= width
class Solution {
public:
    int minDistance(int height, int width, vector<int>& tree, vector<int>& squirrel, vector<vector<int>>& nuts) {
        int sum = 0, mindis = INT_MAX;
        for (const auto& nut : nuts) {
            sum += 2 * dis(tree[0], tree[1], nut[0], nut[1]);
        }
        for (const auto& nut : nuts) {
            mindis = min(mindis, sum - dis(tree[0], tree[1], nut[0], nut[1]) + dis(squirrel[0], squirrel[1], nut[0], nut[1]));
        }
        return mindis;
    }

    int dis(int a, int b, int c, int d) {
        return abs(a - c) + abs(b - d);
    }
};

592. 分数加减运算(python)

给定一个表示分数加减运算的字符串 expression ,你需要返回一个字符串形式的计算结果。 

这个结果应该是不可约分的分数,即最简分数。 如果最终结果是一个整数,例如 2,你需要将它转换成分数形式,其分母为 1。所以在上述例子中, 2 应该被转换为 2/1

示例 1:

输入: expression = "-1/2+1/2"
输出: "0/1"

 示例 2:

输入: expression = "-1/2+1/2+1/3"
输出: "1/3"

示例 3:

输入: expression = "1/3-1/2"
输出: "-1/6"

提示:

  • 输入和输出字符串只包含 '0' 到 '9' 的数字,以及 '/''+' 和 '-'。 
  • 输入和输出分数格式均为 ±分子/分母。如果输入的第一个分数或者输出的分数是正数,则 '+' 会被省略掉。
  • 输入只包含合法的最简分数,每个分数的分子分母的范围是  [1,10]。 如果分母是1,意味着这个分数实际上是一个整数。
  • 输入的分数个数范围是 [1,10]。
  • 最终结果的分子与分母保证是 32 位整数范围内的有效整数。
class Solution:
    def fractionAddition(self, expression: str) -> str:
        def gcd(a, b):
            if b == 0:
                return a
            return gcd(b, a % b)

        def lcm(a, b):
            return a * b // gcd(a, b)

        def add(a, b, c, d):
            e = lcm(b, d)
            return (a * e // b + c * e // d, e)

        nums = []
        i = 0
        while i < len(expression):
            if expression[i] == '-':
                sign = -1
                i += 1
            elif expression[i] == '+':
                sign = 1
                i += 1
            else:
                sign = 1
            j = i
            while j < len(expression) and expression[j] != '+' and expression[j] != '-':
                j += 1
            num = expression[i:j]
            nums.append((sign, int(num.split('/')[0]), int(num.split('/')[1])))
            i = j

        res = (0, 1)
        for num in nums:
            res = add(res[0], res[1], num[0] * num[1], num[2])
        if res[0] == 0:
            return '0/1'
        g = gcd(abs(res[0]), res[1])
        return str(res[0] // g) + '/' + str(res[1] // g)

722. 删除注释(C++)

给一个 C++ 程序,删除程序中的注释。这个程序source是一个数组,其中source[i]表示第 i 行源码。 这表示每行源码由 '\n' 分隔。

在 C++ 中有两种注释风格,行内注释和块注释。

字符串// 表示行注释,表示//和其右侧的其余字符应该被忽略。
字符串/* 表示一个块注释,它表示直到下一个(非重叠)出现的*/之间的所有字符都应该被忽略。(阅读顺序为从左到右)非重叠是指,字符串/*/并没有结束块注释,因为注释的结尾与开头相重叠。
第一个有效注释优先于其他注释。

如果字符串//出现在块注释中会被忽略。
同样,如果字符串/*出现在行或块注释中也会被忽略。
如果一行在删除注释之后变为空字符串,那么不要输出该行。即,答案列表中的每个字符串都是非空的。

样例中没有控制字符,单引号或双引号字符。

比如,source = "string s = "/* Not a comment. */";" 不会出现在测试样例里。
此外,没有其他内容(如定义或宏)会干扰注释。

我们保证每一个块注释最终都会被闭合, 所以在行或块注释之外的/*总是开始新的注释。

最后,隐式换行符可以通过块注释删除。 有关详细信息,请参阅下面的示例。

从源代码中删除注释后,需要以相同的格式返回源代码。

示例 1:

输入: source = ["/*Test program */", "int main()", "{ ", "  // variable declaration ", "int a, b, c;", "/* This is a test", "   multiline  ", "   comment for ", "   testing */", "a = b + c;", "}"]
输出: ["int main()","{ ","  ","int a, b, c;","a = b + c;","}"]
解释: 示例代码可以编排成这样:
/*Test program */
int main()

  // variable declaration 
int a, b, c;
/* This is a test
   multiline  
   comment for 
   testing */
a = b + c;
}
第 1 行和第 6-9 行的字符串 /* 表示块注释。第 4 行的字符串 // 表示行注释。
编排后: 
int main()

  
int a, b, c;
a = b + c;
}
示例 2:

输入: source = ["a/*comment", "line", "more_comment*/b"]
输出: ["ab"]
解释: 原始的 source 字符串是 "a/*comment\nline\nmore_comment*/b", 其中我们用粗体显示了换行符。删除注释后,隐含的换行符被删除,留下字符串 "ab" 用换行符分隔成数组时就是 ["ab"].
 

提示:

1 <= source.length <= 100
0 <= source[i].length <= 80
source[i] 由可打印的 ASCII 字符组成。
每个块注释都会被闭合。
给定的源码中不会有单引号、双引号或其他控制字符。


class Solution {
public:
    vector<string> removeComments(vector<string>& source) {
        vector<string> res;
        bool inBlock = false;
        string cur = "";
        for (string s : source) {
            for (int i = 0; i < s.size(); i++) {
                if (!inBlock && i + 1 < s.size() && s[i] == '/' && s[i + 1] == '/') {
                    break;
                } else if (!inBlock && i + 1 < s.size() && s[i] == '/' && s[i + 1] == '*') {
                    inBlock = true;
                    i++;
                } else if (inBlock && i + 1 < s.size() && s[i] == '*' && s[i + 1] == '/') {
                    inBlock = false;
                    i++;
                } else if (!inBlock) {
                    cur += s[i];
                }
            }
            if (!inBlock && cur != "") {
                res.push_back(cur);
                cur = "";
            }
        }
        return res;
    }
};

1041. 困于环中的机器人(python)

在无限的平面上,机器人最初位于 (0, 0) 处,面朝北方。注意:

  • 北方向 是y轴的正方向。
  • 南方向 是y轴的负方向。
  • 东方向 是x轴的正方向。
  • 西方向 是x轴的负方向。

机器人可以接受下列三条指令之一:

  • "G":直走 1 个单位
  • "L":左转 90 度
  • "R":右转 90 度

机器人按顺序执行指令 instructions,并一直重复它们。

只有在平面中存在环使得机器人永远无法离开时,返回 true。否则,返回 false

示例 1:

输入:instructions = "GGLLGG"
输出:true
解释:机器人最初在(0,0)处,面向北方。
“G”:移动一步。位置:(0,1)方向:北。
“G”:移动一步。位置:(0,2).方向:北。
“L”:逆时针旋转90度。位置:(0,2).方向:西。
“L”:逆时针旋转90度。位置:(0,2)方向:南。
“G”:移动一步。位置:(0,1)方向:南。
“G”:移动一步。位置:(0,0)方向:南。
重复指令,机器人进入循环:(0,0)——>(0,1)——>(0,2)——>(0,1)——>(0,0)。
在此基础上,我们返回true。

示例 2:

输入:instructions = "GG"
输出:false
解释:机器人最初在(0,0)处,面向北方。
“G”:移动一步。位置:(0,1)方向:北。
“G”:移动一步。位置:(0,2).方向:北。
重复这些指示,继续朝北前进,不会进入循环。
在此基础上,返回false。

示例 3:

输入:instructions = "GL"
输出:true
解释:机器人最初在(0,0)处,面向北方。
“G”:移动一步。位置:(0,1)方向:北。
“L”:逆时针旋转90度。位置:(0,1).方向:西。
“G”:移动一步。位置:(- 1,1)方向:西。
“L”:逆时针旋转90度。位置:(- 1,1)方向:南。
“G”:移动一步。位置:(- 1,0)方向:南。
“L”:逆时针旋转90度。位置:(- 1,0)方向:东方。
“G”:移动一步。位置:(0,0)方向:东方。
“L”:逆时针旋转90度。位置:(0,0)方向:北。
重复指令,机器人进入循环:(0,0)——>(0,1)——>(- 1,1)——>(- 1,0)——>(0,0)。
在此基础上,我们返回true。

提示:

  • 1 <= instructions.length <= 100
  • instructions[i] 仅包含 'G', 'L', 'R'
class Solution:
    def isRobotBounded(self, instructions: str) -> bool:
        # 初始化机器人位置和方向
        x, y = 0, 0
        dx, dy = 0, 1
        
        # 按照指令移动机器人
        for i in instructions:
            if i == 'G':
                x += dx
                y += dy
            elif i == 'L':
                dx, dy = -dy, dx
            elif i == 'R':
                dx, dy = dy, -dx
        
        # 如果机器人回到了原点或者方向不是初始方向,就说明存在循环
        return (x, y) == (0, 0) or (dx, dy) != (0, 1)

1091. 二进制矩阵中的最短路径

给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1 。

二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:

路径途经的所有单元格的值都是 0 。
路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
畅通路径的长度 是该路径途经的单元格总数。



示例 1:


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


输入:grid = [[0,0,0],[1,1,0],[1,1,0]]
输出:4
示例 3:

输入:grid = [[1,0,0],[1,1,0],[1,1,0]]
输出:-1


提示:

n == grid.length
n == grid[i].length
1 <= n <= 100
grid[i][j] 为 0 或 1


 

class Solution {
public:
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        int n = grid.size();
        if (grid[0][0] == 1 || grid[n-1][n-1] == 1) {
            return -1;
        }
        vector<vector<int>> dirs = {{-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}};
        queue<pair<int,int>> q;
        q.push({0,0});
        grid[0][0] = 1;
        int steps = 1;
        while (!q.empty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                auto curr = q.front();
                q.pop();
                if (curr.first == n-1 && curr.second == n-1) {
                    return steps;
                }
                for (auto dir : dirs) {
                    int x = curr.first + dir[0];
                    int y = curr.second + dir[1];
                    if (x >= 0 && x < n && y >= 0 && y < n && grid[x][y] == 0) {
                        q.push({x,y});
                        grid[x][y] = 1;
                    }
                }
            }
            steps++;
        }
        return -1;
    }
};

1285. 找到连续区间的开始和结束数字(MySql)

表:Logs

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| log_id        | int     |
+---------------+---------+
id 是上表的主键。
上表的每一行包含日志表中的一个 ID。
 

后来一些 ID 从 Logs 表中删除。编写一个 SQL 查询得到 Logs 表中的连续区间的开始数字和结束数字。

将查询表按照 start_id 排序。

查询结果格式如下面的例子。

示例 1:

输入:
Logs 表:
+------------+
| log_id     |
+------------+
| 1          |
| 2          |
| 3          |
| 7          |
| 8          |
| 10         |
+------------+
输出:
+------------+--------------+
| start_id   | end_id       |
+------------+--------------+
| 1          | 3            |
| 7          | 8            |
| 10         | 10           |
+------------+--------------+
解释:
结果表应包含 Logs 表中的所有区间。
从 1 到 3 在表中。
从 4 到 6 不在表中。
从 7 到 8 在表中。
9 不在表中。
10 在表中。

SELECT MIN(log_id) AS start_id, MAX(log_id) AS end_id
FROM (
  SELECT log_id, log_id - ROW_NUMBER() OVER (ORDER BY log_id) AS group_id
  FROM Logs
) AS temp
GROUP BY group_id
ORDER BY start_id;

1294. 不同国家的天气类型(MySql)

国家表:Countries

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| country_id    | int     |
| country_name  | varchar |
+---------------+---------+
country_id 是这张表的主键。
该表的每行有 country_id 和 country_name 两列。
 

天气表:Weather

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| country_id    | int     |
| weather_state | varchar |
| day           | date    |
+---------------+---------+
(country_id, day) 是该表的复合主键。
该表的每一行记录了某个国家某一天的天气情况。
 

写一段 SQL 来找到表中每个国家在 2019 年 11 月的天气类型。

天气类型的定义如下:当 weather_state 的平均值小于或等于15返回 Cold,当 weather_state 的平均值大于或等于 25 返回 Hot,否则返回 Warm。

你可以以任意顺序返回你的查询结果。

查询结果格式如下所示:

Countries table:
+------------+--------------+
| country_id | country_name |
+------------+--------------+
| 2          | USA          |
| 3          | Australia    |
| 7          | Peru         |
| 5          | China        |
| 8          | Morocco      |
| 9          | Spain        |
+------------+--------------+
Weather table:
+------------+---------------+------------+
| country_id | weather_state | day        |
+------------+---------------+------------+
| 2          | 15            | 2019-11-01 |
| 2          | 12            | 2019-10-28 |
| 2          | 12            | 2019-10-27 |
| 3          | -2            | 2019-11-10 |
| 3          | 0             | 2019-11-11 |
| 3          | 3             | 2019-11-12 |
| 5          | 16            | 2019-11-07 |
| 5          | 18            | 2019-11-09 |
| 5          | 21            | 2019-11-23 |
| 7          | 25            | 2019-11-28 |
| 7          | 22            | 2019-12-01 |
| 7          | 20            | 2019-12-02 |
| 8          | 25            | 2019-11-05 |
| 8          | 27            | 2019-11-15 |
| 8          | 31            | 2019-11-25 |
| 9          | 7             | 2019-10-23 |
| 9          | 3             | 2019-12-23 |
+------------+---------------+------------+
Result table:
+--------------+--------------+
| country_name | weather_type |
+--------------+--------------+
| USA          | Cold         |
| Austraila    | Cold         |
| Peru         | Hot          |
| China        | Warm         |
| Morocco      | Hot          |
+--------------+--------------+
USA 11 月的平均 weather_state 为 (15) / 1 = 15 所以天气类型为 Cold。
Australia 11 月的平均 weather_state 为 (-2 + 0 + 3) / 3 = 0.333 所以天气类型为 Cold。
Peru 11 月的平均 weather_state 为 (25) / 1 = 25 所以天气类型为 Hot。
China 11 月的平均 weather_state 为 (16 + 18 + 21) / 3 = 18.333 所以天气类型为 Warm。
Morocco 11 月的平均 weather_state 为 (25 + 27 + 31) / 3 = 27.667 所以天气类型为 Hot。
我们并不知道 Spain 在 11 月的 weather_state 情况所以无需将他包含在结果中。

SELECT c.country_name, 
       CASE 
         WHEN AVG(w.weather_state) <= 15 THEN 'Cold' 
         WHEN AVG(w.weather_state) >= 25 THEN 'Hot' 
         ELSE 'Warm' 
       END AS weather_type 
FROM   Countries c 
       JOIN Weather w 
         ON c.country_id = w.country_id 
WHERE  w.day BETWEEN '2019-11-01' AND '2019-11-30' 
GROUP  BY c.country_name;

1303. 求团队人数(MySql)

员工表:Employee

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| employee_id   | int     |
| team_id       | int     |
+---------------+---------+
employee_id 字段是这张表的主键,表中的每一行都包含每个员工的 ID 和他们所属的团队。
编写一个 SQL 查询,以求得每个员工所在团队的总人数。

查询结果中的顺序无特定要求。

查询结果格式示例如下:

Employee Table:
+-------------+------------+
| employee_id | team_id    |
+-------------+------------+
|     1       |     8      |
|     2       |     8      |
|     3       |     8      |
|     4       |     7      |
|     5       |     9      |
|     6       |     9      |
+-------------+------------+
Result table:
+-------------+------------+
| employee_id | team_size  |
+-------------+------------+
|     1       |     3      |
|     2       |     3      |
|     3       |     3      |
|     4       |     1      |
|     5       |     2      |
|     6       |     2      |
+-------------+------------+
ID 为 1、2、3 的员工是 team_id 为 8 的团队的成员,
ID 为 4 的员工是 team_id 为 7 的团队的成员,
ID 为 5、6 的员工是 team_id 为 9 的团队的成员。

SELECT employee_id, 
       (SELECT COUNT(*) FROM Employee WHERE team_id = e.team_id) AS team_size
FROM Employee e

1350. 院系无效的学生(MySql)

院系表: Departments

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| name          | varchar |
+---------------+---------+
id 是该表的主键
该表包含一所大学每个院系的 id 信息
 

学生表: Students

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| name          | varchar |
| department_id | int     |
+---------------+---------+
id 是该表的主键
该表包含一所大学每个学生的 id 和他/她就读的院系信息
 

写一条 SQL 语句以查询那些所在院系不存在的学生的 id 和姓名

可以以 任何顺序 返回结果。

下面是返回结果格式的例子。

示例 1:

输入:
Departments 表:
+------+--------------------------+
| id   | name                     |
+------+--------------------------+
| 1    | Electrical Engineering   |
| 7    | Computer Engineering     |
| 13   | Bussiness Administration |
+------+--------------------------+
Students 表:
+------+----------+---------------+
| id   | name     | department_id |
+------+----------+---------------+
| 23   | Alice    | 1             |
| 1    | Bob      | 7             |
| 5    | Jennifer | 13            |
| 2    | John     | 14            |
| 4    | Jasmine  | 77            |
| 3    | Steve    | 74            |
| 6    | Luis     | 1             |
| 8    | Jonathan | 7             |
| 7    | Daiana   | 33            |
| 11   | Madelynn | 1             |
+------+----------+---------------+
输出:
+------+----------+
| id   | name     |
+------+----------+
| 2    | John     |
| 7    | Daiana   |
| 4    | Jasmine  |
| 3    | Steve    |
+------+----------+
解释:
John, Daiana, Steve 和 Jasmine 所在的院系分别是 14, 33, 74 和 77, 其中 14, 33, 74 和 77 并不存在于院系表

SELECT id, name
FROM Students
WHERE department_id NOT IN (SELECT id FROM Departments)

1355. 活动参与者(MySql)

表: Friends

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| name          | varchar |
| activity      | varchar |
+---------------+---------+
id 是朋友的 id 和该表的主键
name 是朋友的名字
activity 是朋友参加的活动的名字
 

表: Activities

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| name          | varchar |
+---------------+---------+
id 是该表的主键
name 是活动的名字
 

写一条 SQL 查询那些既没有最多,也没有最少参与者的活动的名字

Activities 表中的任意活动都有在 Friends 中参与过

可以以 任何顺序 返回结果。

下面是查询结果格式的例子。

示例 1:

输入:
Friends 表:
+------+--------------+---------------+
| id   | name         | activity      |
+------+--------------+---------------+
| 1    | Jonathan D.  | Eating        |
| 2    | Jade W.      | Singing       |
| 3    | Victor J.    | Singing       |
| 4    | Elvis Q.     | Eating        |
| 5    | Daniel A.    | Eating        |
| 6    | Bob B.       | Horse Riding  |
+------+--------------+---------------+
Activities 表:
+------+--------------+
| id   | name         |
+------+--------------+
| 1    | Eating       |
| 2    | Singing      |
| 3    | Horse Riding |
+------+--------------+
输出:
+--------------+
| activity     |
+--------------+
| Singing      |
+--------------+
解释:
Eating 活动有三个人参加, 是最多人参加的活动 (Jonathan D. , Elvis Q. and Daniel A.)
Horse Riding 活动有一个人参加, 是最少人参加的活动 (Bob B.)
Singing 活动有两个人参加 (Victor J. and Jade W.)

SELECT a.name AS activity
FROM Activities a
JOIN Friends f ON a.name = f.activity
GROUP BY a.name
HAVING COUNT(DISTINCT f.id) NOT IN (
  (SELECT COUNT(DISTINCT f1.id) FROM Friends f1 GROUP BY f1.activity ORDER BY COUNT(DISTINCT f1.id) DESC LIMIT 1),
  (SELECT COUNT(DISTINCT f2.id) FROM Friends f2 GROUP BY f2.activity ORDER BY COUNT(DISTINCT f2.id) ASC LIMIT 1)
)

1398. 购买了产品 A 和产品 B 却没有购买产品 C 的顾客(MySql)

Customers 表:

+---------------------+---------+
| Column Name         | Type    |
+---------------------+---------+
| customer_id         | int     |
| customer_name       | varchar |
+---------------------+---------+
customer_id 是这张表中具有唯一值的列。
customer_name 是顾客的名称。

Orders 表:

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| order_id      | int     |
| customer_id   | int     |
| product_name  | varchar |
+---------------+---------+
order_id 是这张表中具有唯一值的列。
customer_id 是购买了名为 "product_name" 产品顾客的id。

请你编写解决方案,报告购买了产品 "A""B" 但没有购买产品 "C" 的客户的 customer_id 和 customer_name,因为我们想推荐他们购买这样的产品。

返回按 customer_id 排序 的结果表。

返回结果格式如下所示。

示例 1:

输入:
Customers table:
+-------------+---------------+
| customer_id | customer_name |
+-------------+---------------+
| 1           | Daniel        |
| 2           | Diana         |
| 3           | Elizabeth     |
| 4           | Jhon          |
+-------------+---------------+

Orders table:
+------------+--------------+---------------+
| order_id   | customer_id  | product_name  |
+------------+--------------+---------------+
| 10         |     1        |     A         |
| 20         |     1        |     B         |
| 30         |     1        |     D         |
| 40         |     1        |     C         |
| 50         |     2        |     A         |
| 60         |     3        |     A         |
| 70         |     3        |     B         |
| 80         |     3        |     D         |
| 90         |     4        |     C         |
+------------+--------------+---------------+
输出:
+-------------+---------------+
| customer_id | customer_name |
+-------------+---------------+
| 3           | Elizabeth     |
+-------------+---------------+
解释:
只有 customer_id 为 3 的顾客购买了产品 A 和产品 B ,却没有购买产品 C 。
SELECT c.customer_id, c.customer_name
FROM Customers c
WHERE c.customer_id NOT IN (
  SELECT o.customer_id
  FROM Orders o
  WHERE o.product_name = 'C'
) AND c.customer_id IN (
  SELECT o.customer_id
  FROM Orders o
  WHERE o.product_name = 'A'
) AND c.customer_id IN (
  SELECT o.customer_id
  FROM Orders o
  WHERE o.product_name = 'B'
)
ORDER BY c.customer_id;

1564. 把箱子放进仓库里 I(C++)

给定两个正整数数组 boxes 和 warehouse ,分别包含单位宽度的箱子的高度,以及仓库中 n 个房间各自的高度。仓库的房间分别从 0 到 n - 1 自左向右编号, warehouse[i] (索引从 0 开始)是第 i 个房间的高度。

箱子放进仓库时遵循下列规则:

  • 箱子不可叠放。
  • 你可以重新调整箱子的顺序。
  • 箱子只能从左向右推进仓库中。
  • 如果仓库中某房间的高度小于某箱子的高度,则这个箱子和之后的箱子都会停在这个房间的前面。

你最多可以在仓库中放进多少个箱子?

示例 1:

输入:boxes = [4,3,4,1], warehouse = [5,3,3,4,1]
输出:3
解释:

我们可以先把高度为 1 的箱子放入 4 号房间,然后再把高度为 3 的箱子放入 1 号、 2 号或 3 号房间,最后再把高度为 4 的箱子放入 0 号房间。
我们不可能把所有 4 个箱子全部放进仓库里。

示例 2:

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

我们注意到,不可能把高度为 4 的箱子放入仓库中,因为它不能通过高度为 3 的房间。
而且,对于最后两个房间 2 号和 3 号来说,只有高度为 1 的箱子可以放进去。
我们最多可以放进 3 个箱子,如上图所示。黄色的箱子也可以放入 2 号房间。
交换橙色和绿色箱子的位置,或是将这两个箱子与红色箱子交换位置,也是可以的。

示例 3:

输入:boxes = [1,2,3], warehouse = [1,2,3,4]
输出:1
解释:由于第一个房间的高度为 1,我们只能放进高度为 1 的箱子。

提示:

  • n == warehouse.length
  • 1 <= boxes.length, warehouse.length <= 10^5
  • 1 <= boxes[i], warehouse[i] <= 10^9
class Solution {
public:
    int maxBoxesInWarehouse(vector<int>& boxes, vector<int>& warehouse) {
        sort(boxes.begin(),boxes.end());
        int length01 = boxes.size();
        int length02 = warehouse.size();
        int ans = 0, j = 0;
        for (int i = 1; i < length02; ++i) {
            warehouse[i] = min(warehouse[i], warehouse[i-1]);  // 更新区间最小值
        }
        for (int i = length02-1; i >= 0; --i) {
            if (j <= length01-1 && boxes[j] <= warehouse[i]) {
                ans += 1;
                j += 1;
            }
        }
        return ans;
    }
};

1583. 统计不开心的朋友(python)

给你一份 n 位朋友的亲近程度列表,其中 n 总是 偶数 。

对每位朋友 ipreferences[i] 包含一份 按亲近程度从高到低排列 的朋友列表。换句话说,排在列表前面的朋友与 i 的亲近程度比排在列表后面的朋友更高。每个列表中的朋友均以 0 到 n-1 之间的整数表示。

所有的朋友被分成几对,配对情况以列表 pairs 给出,其中 pairs[i] = [xi, yi] 表示 xi 与 yi 配对,且 yi 与 xi 配对。

但是,这样的配对情况可能会使其中部分朋友感到不开心。在 x 与 y 配对且 u 与 v 配对的情况下,如果同时满足下述两个条件,x 就会不开心:

  • x 与 u 的亲近程度胜过 x 与 y,且
  • u 与 x 的亲近程度胜过 u 与 v

返回 不开心的朋友的数目 。

示例 1:

输入:n = 4, preferences = [[1, 2, 3], [3, 2, 0], [3, 1, 0], [1, 2, 0]], pairs = [[0, 1], [2, 3]]
输出:2
解释:
朋友 1 不开心,因为:
- 1 与 0 配对,但 1 与 3 的亲近程度比 1 与 0 高,且
- 3 与 1 的亲近程度比 3 与 2 高。
朋友 3 不开心,因为:
- 3 与 2 配对,但 3 与 1 的亲近程度比 3 与 2 高,且
- 1 与 3 的亲近程度比 1 与 0 高。
朋友 0 和 2 都是开心的。

示例 2:

输入:n = 2, preferences = [[1], [0]], pairs = [[1, 0]]
输出:0
解释:朋友 0 和 1 都开心。

示例 3:

输入:n = 4, preferences = [[1, 3, 2], [2, 3, 0], [1, 3, 0], [0, 2, 1]], pairs = [[1, 3], [0, 2]]
输出:4

提示:

  • 2 <= n <= 500
  • n 是偶数
  • preferences.length == n
  • preferences[i].length == n - 1
  • 0 <= preferences[i][j] <= n - 1
  • preferences[i] 不包含 i
  • preferences[i] 中的所有值都是独一无二的
  • pairs.length == n/2
  • pairs[i].length == 2
  • xi != yi
  • 0 <= xi, yi <= n - 1
  • 每位朋友都 恰好 被包含在一对中
class Solution:
    def unhappyFriends(self, n: int, preferences: List[List[int]], pairs: List[List[int]]) -> int:
        # 构建亲近程度字典
        pref_dict = {}
        for i in range(n):
            pref_dict[i] = {}
            for j in range(n-1):
                pref_dict[i][preferences[i][j]] = j
        
        # 构建配对字典
        pair_dict = {}
        for pair in pairs:
            pair_dict[pair[0]] = pair[1]
            pair_dict[pair[1]] = pair[0]
        
        unhappy = 0
        for x in range(n):
            y = pair_dict[x]
            for u in range(n):
                if u == x or u == y:
                    continue
                v = pair_dict[u]
                if pref_dict[x][u] < pref_dict[x][y] and pref_dict[u][x] < pref_dict[u][v]:
                    unhappy += 1
                    break
        
        return unhappy

2490. 回环句(C++)

句子 是由单个空格分隔的一组单词,且不含前导或尾随空格。

例如,"Hello World"、"HELLO"、"hello world hello world" 都是符合要求的句子。
单词 仅 由大写和小写英文字母组成。且大写和小写字母会视作不同字符。

如果句子满足下述全部条件,则认为它是一个 回环句 :

单词的最后一个字符和下一个单词的第一个字符相等。
最后一个单词的最后一个字符和第一个单词的第一个字符相等。
例如,"leetcode exercises sound delightful"、"eetcode"、"leetcode eats soul" 都是回环句。然而,"Leetcode is cool"、"happy Leetcode"、"Leetcode" 和 "I like Leetcode" 都 不 是回环句。

给你一个字符串 sentence ,请你判断它是不是一个回环句。如果是,返回 true ;否则,返回 false 。

示例 1:

输入:sentence = "leetcode exercises sound delightful"
输出:true
解释:句子中的单词是 ["leetcode", "exercises", "sound", "delightful"] 。
- leetcode 的最后一个字符和 exercises 的第一个字符相等。
- exercises 的最后一个字符和 sound 的第一个字符相等。
- sound 的最后一个字符和 delightful 的第一个字符相等。
- delightful 的最后一个字符和 leetcode 的第一个字符相等。
这个句子是回环句。
示例 2:

输入:sentence = "eetcode"
输出:true
解释:句子中的单词是 ["eetcode"] 。
- eetcode 的最后一个字符和 eetcode 的第一个字符相等。
这个句子是回环句。
示例 3:

输入:sentence = "Leetcode is cool"
输出:false
解释:句子中的单词是 ["Leetcode", "is", "cool"] 。
- Leetcode 的最后一个字符和 is 的第一个字符 不 相等。 
这个句子 不 是回环句。
 

提示:

1 <= sentence.length <= 500
sentence 仅由大小写英文字母和空格组成
sentence 中的单词由单个空格进行分隔
不含任何前导或尾随空格

class Solution {
public:
    bool isCircularSentence(string sentence) {
        vector<string> words;
        string word = "";
        for (char c : sentence) {
            if (c == ' ') {
                words.push_back(word);
                word = "";
            } else {
                word += c;
            }
        }
        words.push_back(word); // 加入最后一个单词
        int n = words.size();
        for (int i = 0; i < n - 1; i++) {
            if (words[i][words[i].size() - 1] != words[i + 1][0]) {
                return false;
            }
        }
        return words[n - 1][words[n - 1].size() - 1] == words[0][0];
    }
};

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在VS Code上力扣LeetCode目,首先需要进行以下几步操作: 1. 安装VS Code插件:在VS Code中搜索并安装LeetCode插件。这个插件可以提供LeetCode目的在线编写和提交功能,以及自动测试和调试代码的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【史上最强代码编辑器VS Code】之VS Code力扣LeetCode目](https://blog.csdn.net/weixin_44553006/article/details/105183522)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [在 vscode 上力扣 Leetcode 可以这样来](https://blog.csdn.net/u012190388/article/details/121277555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [leetcode答案-algo-study:从零开始力扣(LeetCode),JavaScript语言,算法](https://download.csdn.net/download/weixin_38680764/19920528)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值