diff --git a/Index/DFS.md b/Index/DFS.md index d4da9378..41da213e 100644 --- a/Index/DFS.md +++ b/Index/DFS.md @@ -61,6 +61,7 @@ | [1022. 从根到叶的二进制数之和](https://leetcode.cn/problems/sum-of-root-to-leaf-binary-numbers/) | [LeetCode 题解链接](https://leetcode.cn/problems/sum-of-root-to-leaf-binary-numbers/solution/by-ac_oier-1905/) | 简单 | 🤩🤩🤩🤩 | | [1239. 串联字符串的最大长度](https://leetcode-cn.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/solution/gong-shui-san-xie-yi-ti-san-jie-jian-zhi-nfeb/) | 中等 | 🤩🤩🤩 | | [1302. 层数最深叶子节点的和](https://leetcode.cn/problems/deepest-leaves-sum/) | [LeetCode 题解链接](https://leetcode.cn/problems/deepest-leaves-sum/solution/by-ac_oier-srst/) | 中等 | 🤩🤩🤩🤩 | +| [1457. 二叉树中的伪回文路径](https://leetcode.cn/problems/pseudo-palindromic-paths-in-a-binary-tree/) | [LeetCode 题解链接](https://leetcode.cn/problems/pseudo-palindromic-paths-in-a-binary-tree/solutions/2540912/gong-shui-san-xie-gao-xiao-ji-jian-de-we-f2gb/) | 中等 | 🤩🤩🤩🤩 | | [1609. 奇偶树](https://leetcode-cn.com/problems/even-odd-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/even-odd-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-bfs-d-kuyi/) | 中等 | 🤩🤩🤩🤩🤩 | | [1723. 完成所有工作的最短时间](https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/solution/gong-shui-san-xie-yi-ti-shuang-jie-jian-4epdd/) | 困难 | 🤩🤩🤩 | | [1766. 互质树](https://leetcode-cn.com/problems/tree-of-coprimes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/tree-of-coprimes/solution/bu-tai-yi-yang-de-dfs-ji-lu-suo-you-zui-d3xeu/) | 困难 | 🤩🤩🤩🤩 | diff --git "a/Index/\344\272\214\345\210\206.md" "b/Index/\344\272\214\345\210\206.md" index 12a806ea..91b69b3d 100644 --- "a/Index/\344\272\214\345\210\206.md" +++ "b/Index/\344\272\214\345\210\206.md" @@ -76,6 +76,7 @@ | [2055. 蜡烛之间的盘子](https://leetcode-cn.com/problems/plates-between-candles/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/plates-between-candles/solution/gong-shui-san-xie-er-fen-qian-zhui-he-yu-0qt0/) | 中等 | 🤩🤩🤩🤩 | | [2258. 逃离火灾](https://leetcode.cn/problems/escape-the-spreading-fire/) | [LeetCode 题解链接](https://leetcode.cn/problems/escape-the-spreading-fire/solutions/2518985/gong-shui-san-xie-xiang-jie-ru-he-cong-e-458x/) | 困难 | 🤩🤩🤩🤩🤩 | | [2300. 咒语和药水的成功对数](https://leetcode.cn/problems/successful-pairs-of-spells-and-potions/) | [LeetCode 题解链接](https://leetcode.cn/problems/successful-pairs-of-spells-and-potions/solutions/2520333/gong-shui-san-xie-jing-dian-er-fen-yun-y-86y0/) | 中等 | 🤩🤩🤩🤩 | +| [2824. 统计和小于目标的下标对数目](https://leetcode.cn/problems/count-pairs-whose-sum-is-less-than-target/) | [LeetCode 题解链接](https://leetcode.cn/problems/count-pairs-whose-sum-is-less-than-target/solutions/2539761/gong-shui-san-xie-xiang-jie-zuo-zhao-you-1yji/) | 简单 | 🤩🤩🤩🤩 | | [剑指 Offer 04. 二维数组中的查找](https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/) | [LeetCode 题解链接](https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/solution/by-ac_oier-7jo0/) | 中等 | 🤩🤩🤩🤩🤩 | | [剑指 Offer 11. 旋转数组的最小数字](https://leetcode.cn/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/) | [LeetCode 题解链接](https://leetcode.cn/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/solution/by-ac_oier-p751/) | 简单 | 🤩🤩🤩🤩 | | [剑指 Offer 53 - I. 在排序数组中查找数字 I](https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/solution/gong-shui-san-xie-liang-chong-er-fen-ton-3epx/) | 简单 | 🤩🤩🤩🤩🤩 | diff --git "a/Index/\344\275\215\350\277\220\347\256\227.md" "b/Index/\344\275\215\350\277\220\347\256\227.md" index 21138065..a2cf5d42 100644 --- "a/Index/\344\275\215\350\277\220\347\256\227.md" +++ "b/Index/\344\275\215\350\277\220\347\256\227.md" @@ -19,6 +19,7 @@ | [762. 二进制表示中质数个计算置位](https://leetcode-cn.com/problems/prime-number-of-set-bits-in-binary-representation/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/prime-number-of-set-bits-in-binary-representation/solution/by-ac_oier-w50x/) | 简单 | 🤩🤩🤩🤩 | | [1178. 猜字谜](https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/solution/xiang-jin-zhu-shi-xiang-jie-po-su-wei-yu-3cr2/) | 困难 | 🤩🤩🤩🤩 | | [1252. 奇数值单元格的数目](https://leetcode.cn/problems/cells-with-odd-values-in-a-matrix/) | [LeetCode 题解链接](https://leetcode.cn/problems/cells-with-odd-values-in-a-matrix/solution/by-ac_oier-p0za/) | 简单 | 🤩🤩🤩 | +| [1457. 二叉树中的伪回文路径](https://leetcode.cn/problems/pseudo-palindromic-paths-in-a-binary-tree/) | [LeetCode 题解链接](https://leetcode.cn/problems/pseudo-palindromic-paths-in-a-binary-tree/solutions/2540912/gong-shui-san-xie-gao-xiao-ji-jian-de-we-f2gb/) | 中等 | 🤩🤩🤩🤩 | | [1711. 大餐计数](https://leetcode-cn.com/problems/count-good-meals/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-good-meals/solution/gong-shui-san-xie-xiang-jie-san-chong-gu-nn4f/) | 中等 | 🤩🤩🤩 | | [2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/solution/by-ac_oier-dos6/) | 困难 | 🤩🤩🤩🤩 | | [2103. 环和杆](https://leetcode.cn/problems/rings-and-rods/) | [LeetCode 题解链接](https://leetcode.cn/problems/rings-and-rods/solutions/2509056/gong-shui-san-xie-liang-ge-jiao-du-jin-x-r1v1/) | 简单 | 🤩🤩🤩🤩 | diff --git "a/Index/\345\217\214\346\214\207\351\222\210.md" "b/Index/\345\217\214\346\214\207\351\222\210.md" index 44acc619..a99c1cb2 100644 --- "a/Index/\345\217\214\346\214\207\351\222\210.md" +++ "b/Index/\345\217\214\346\214\207\351\222\210.md" @@ -75,6 +75,7 @@ | [2024. 考试的最大困扰度](https://leetcode-cn.com/problems/maximize-the-confusion-of-an-exam/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximize-the-confusion-of-an-exam/solution/by-ac_oier-2rii/) | 中等 | 🤩🤩🤩🤩 | | [2047. 句子中的有效单词数](https://leetcode-cn.com/problems/number-of-valid-words-in-a-sentence/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-valid-words-in-a-sentence/solution/gong-shui-san-xie-jian-dan-zi-fu-chuan-m-5pcz/) | 简单 | 🤩🤩🤩🤩 | | [2760. 最长奇偶子数组](https://leetcode.cn/problems/longest-even-odd-subarray-with-threshold/) | [LeetCode 题解链接](https://leetcode.cn/problems/longest-even-odd-subarray-with-threshold/solutions/2528837/gong-shui-san-xie-chou-si-bo-chong-tu-ji-n9r1/) | 简单 | 🤩🤩🤩🤩🤩 | +| [2824. 统计和小于目标的下标对数目](https://leetcode.cn/problems/count-pairs-whose-sum-is-less-than-target/) | [LeetCode 题解链接](https://leetcode.cn/problems/count-pairs-whose-sum-is-less-than-target/solutions/2539761/gong-shui-san-xie-xiang-jie-zuo-zhao-you-1yji/) | 简单 | 🤩🤩🤩🤩 | | [面试题 01.05. 一次编辑](https://leetcode.cn/problems/one-away-lcci/) | [LeetCode 题解链接](https://leetcode.cn/problems/one-away-lcci/solution/by-ac_oier-7ml0/) | 中等 | 🤩🤩🤩🤩 | | [面试题 17.09. 第 k 个数](https://leetcode.cn/problems/get-kth-magic-number-lcci/) | [LeetCode 题解链接](https://leetcode.cn/problems/get-kth-magic-number-lcci/solution/by-ac_oier-2czm/) | 中等 | 🤩🤩🤩🤩🤩 | | [面试题 17.11. 单词距离](https://leetcode.cn/problems/find-closest-lcci/) | [LeetCode 题解链接](https://leetcode.cn/problems/find-closest-lcci/solution/by-ac_oier-0hv9/) | 中等 | 🤩🤩🤩🤩 | diff --git "a/Index/\345\223\210\345\270\214\350\241\250.md" "b/Index/\345\223\210\345\270\214\350\241\250.md" index 84bf0cca..3dcc2f13 100644 --- "a/Index/\345\223\210\345\270\214\350\241\250.md" +++ "b/Index/\345\223\210\345\270\214\350\241\250.md" @@ -72,6 +72,7 @@ | [1268. 搜索推荐系统](https://leetcode.cn/problems/search-suggestions-system/) | [LeetCode 题解链接](https://leetcode.cn/problems/search-suggestions-system/solution/gong-shui-san-xie-yi-ti-shuang-jie-pai-x-gnmu/) | 中等 | 🤩🤩🤩🤩 | | [1282. 用户分组](https://leetcode.cn/problems/group-the-people-given-the-group-size-they-belong-to/) | [LeetCode 题解链接](https://leetcode.cn/problems/group-the-people-given-the-group-size-they-belong-to/solution/by-ac_oier-z1bg/) | 中等 | 🤩🤩🤩🤩🤩 | | [1331. 数组序号转换](https://leetcode.cn/problems/rank-transform-of-an-array/) | [LeetCode 题解链接](https://leetcode.cn/problems/rank-transform-of-an-array/solution/by-ac_oier-j70n/) | 简单 | 🤩🤩🤩🤩 | +| [1410. HTML 实体解析器](https://leetcode.cn/problems/html-entity-parser/) | [LeetCode 题解链接](https://leetcode.cn/problems/html-entity-parser/solutions/2538217/gong-shui-san-xie-jing-dian-zi-fu-chuan-rvdh3/) | 中等 | 🤩🤩🤩 | | [1418. 点菜展示表](https://leetcode-cn.com/problems/display-table-of-food-orders-in-a-restaurant/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/display-table-of-food-orders-in-a-restaurant/solution/gong-shui-san-xie-ha-xi-biao-yu-hong-hei-jmli/) | 中等 | 🤩🤩🤩 | | [1436. 旅行终点站](https://leetcode-cn.com/problems/destination-city/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/destination-city/solution/gong-shui-san-xie-jian-dan-fang-jia-mo-n-y47c/) | 简单 | 🤩🤩🤩🤩🤩 | | [1442. 形成两个异或相等数组的三元组数目](https://leetcode-cn.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/solution/gong-shui-san-xie-xiang-jie-shi-yong-qia-7gzm/) | 中等 | 🤩🤩 | @@ -92,6 +93,7 @@ | [2006. 差的绝对值为 K 的数对数目](https://leetcode-cn.com/problems/count-number-of-pairs-with-absolute-difference-k/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-number-of-pairs-with-absolute-difference-k/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-1jel/) | 简单 | 🤩🤩🤩🤩 | | [2013. 检测正方形](https://leetcode-cn.com/problems/detect-squares/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/detect-squares/solution/gong-shui-san-xie-jian-dan-ha-xi-biao-yu-748e/) | 中等 | 🤩🤩🤩🤩🤩 | | [2034. 股票价格波动](https://leetcode-cn.com/problems/stock-price-fluctuation/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/stock-price-fluctuation/solution/gong-shui-san-xie-shu-ju-jie-gou-mo-ni-t-u6f4/) | 中等 | 🤩🤩🤩🤩 | +| [2336. 无限集中的最小数字](https://leetcode.cn/problems/smallest-number-in-infinite-set/) | [LeetCode 题解链接](https://leetcode.cn/problems/smallest-number-in-infinite-set/solutions/2546157/gong-shui-san-xie-rong-yi-you-gao-xiao-d-431o/) | 中等 | 🤩🤩🤩🤩 | | [2342. 数位和相等数对的最大和](https://leetcode.cn/problems/max-sum-of-a-pair-with-equal-sum-of-digits/) | [LeetCode 题解链接](https://leetcode.cn/problems/max-sum-of-a-pair-with-equal-sum-of-digits/solutions/2531511/gong-shui-san-xie-yong-bian-li-guo-cheng-kt3f/) | 中等 | 🤩🤩🤩🤩 | | [面试题 10.02. 变位词组](https://leetcode-cn.com/problems/group-anagrams-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/group-anagrams-lcci/solution/gong-shui-san-xie-tong-ji-bian-wei-ci-de-0iqe/) | 中等 | 🤩🤩🤩🤩 | | [面试题 17.10. 主要元素](https://leetcode-cn.com/problems/find-majority-element-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-majority-element-lcci/solution/gong-shui-san-xie-yi-ti-shuang-jie-ha-xi-zkht/) | 简单 | 🤩🤩🤩🤩 | diff --git "a/Index/\345\240\206.md" "b/Index/\345\240\206.md" index 5501590c..724192eb 100644 --- "a/Index/\345\240\206.md" +++ "b/Index/\345\240\206.md" @@ -28,6 +28,7 @@ | [1606. 找到处理最多请求的服务器](https://leetcode-cn.com/problems/find-servers-that-handled-most-number-of-requests/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-servers-that-handled-most-number-of-requests/solution/by-ac_oier-zgm6/) | 困难 | 🤩🤩🤩🤩 | | [1705. 吃苹果的最大数目](https://leetcode-cn.com/problems/maximum-number-of-eaten-apples/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-number-of-eaten-apples/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-hfdy0/) | 中等 | 🤩🤩🤩🤩🤩 | | [1834. 单线程 CPU](https://leetcode-cn.com/problems/single-threaded-cpu/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/single-threaded-cpu/solution/gong-shui-san-xie-shu-ju-jie-gou-yun-yon-1qk0/) | 中等 | 🤩🤩🤩🤩 | +| [2336. 无限集中的最小数字](https://leetcode.cn/problems/smallest-number-in-infinite-set/) | [LeetCode 题解链接](https://leetcode.cn/problems/smallest-number-in-infinite-set/solutions/2546157/gong-shui-san-xie-rong-yi-you-gao-xiao-d-431o/) | 中等 | 🤩🤩🤩🤩 | | [2558. 从数量最多的堆取走礼物](https://leetcode.cn/problems/take-gifts-from-the-richest-pile/) | [LeetCode 题解链接](https://leetcode.cn/problems/take-gifts-from-the-richest-pile/solutions/2501825/gong-shui-san-xie-ke-shi-hua-shou-xie-du-pp3a/) | 简单 | 🤩🤩🤩🤩🤩 | | [剑指 Offer 41. 数据流中的中位数](https://leetcode.cn/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/) | [LeetCode 题解链接](https://leetcode.cn/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/solution/by-ac_oier-exn5/) | 困难 | 🤩🤩🤩🤩🤩 | | [剑指 Offer 59 - I. 滑动窗口的最大值](https://leetcode.cn/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/) | [LeetCode 题解链接](https://leetcode.cn/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/solution/by-ac_oier-sjym/) | 困难 | 🤩🤩🤩🤩🤩 | diff --git "a/Index/\346\216\222\345\272\217.md" "b/Index/\346\216\222\345\272\217.md" index 172667f7..4f9b9971 100644 --- "a/Index/\346\216\222\345\272\217.md" +++ "b/Index/\346\216\222\345\272\217.md" @@ -37,6 +37,7 @@ | [1834. 单线程 CPU](https://leetcode-cn.com/problems/single-threaded-cpu/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/single-threaded-cpu/solution/gong-shui-san-xie-shu-ju-jie-gou-yun-yon-1qk0/) | 中等 | 🤩🤩🤩🤩 | | [1838. 最高频元素的频数](https://leetcode-cn.com/problems/frequency-of-the-most-frequent-element/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/frequency-of-the-most-frequent-element/solution/gong-shui-san-xie-cong-mei-ju-dao-pai-xu-kxnk/) | 中等 | 🤩🤩🤩 | | [2300. 咒语和药水的成功对数](https://leetcode.cn/problems/successful-pairs-of-spells-and-potions/) | [LeetCode 题解链接](https://leetcode.cn/problems/successful-pairs-of-spells-and-potions/solutions/2520333/gong-shui-san-xie-jing-dian-er-fen-yun-y-86y0/) | 中等 | 🤩🤩🤩🤩 | +| [2824. 统计和小于目标的下标对数目](https://leetcode.cn/problems/count-pairs-whose-sum-is-less-than-target/) | [LeetCode 题解链接](https://leetcode.cn/problems/count-pairs-whose-sum-is-less-than-target/solutions/2539761/gong-shui-san-xie-xiang-jie-zuo-zhao-you-1yji/) | 简单 | 🤩🤩🤩🤩 | | [面试题 10.02. 变位词组](https://leetcode-cn.com/problems/group-anagrams-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/group-anagrams-lcci/solution/gong-shui-san-xie-tong-ji-bian-wei-ci-de-0iqe/) | 中等 | 🤩🤩🤩🤩 | | [面试题 17.14. 最小K个数](https://leetcode-cn.com/problems/smallest-k-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/smallest-k-lcci/solution/gong-shui-san-xie-yi-ti-si-jie-you-xian-yy5k5/) | 中等 | 🤩🤩🤩🤩 | | [剑指 Offer II 007. 数组中和为 0 的三个数](https://leetcode.cn/problems/1fGaJU/) | [LeetCode 题解链接](https://leetcode.cn/problems/1fGaJU/solution/by-ac_oier-6mfb/) | 中等 | 🤩🤩🤩🤩 | diff --git "a/Index/\346\250\241\346\213\237.md" "b/Index/\346\250\241\346\213\237.md" index 99472079..189bde2d 100644 --- "a/Index/\346\250\241\346\213\237.md" +++ "b/Index/\346\250\241\346\213\237.md" @@ -165,6 +165,7 @@ | [1374. 生成每种字符都是奇数个的字符串](https://leetcode.cn/problems/generate-a-string-with-characters-that-have-odd-counts/) | [LeetCode 题解链接](https://leetcode.cn/problems/generate-a-string-with-characters-that-have-odd-counts/solution/by-ac_oier-i74n/) | 简单 | 🤩🤩 | | [1380. 矩阵中的幸运数](https://leetcode-cn.com/problems/lucky-numbers-in-a-matrix/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/lucky-numbers-in-a-matrix/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-9xwg/) | 简单 | 🤩🤩🤩 | | [1408. 数组中的字符串匹配](https://leetcode.cn/problems/string-matching-in-an-array/) | [LeetCode 题解链接](https://leetcode.cn/problems/string-matching-in-an-array/solution/by-ac_oier-k03v/) | 简单 | 🤩🤩🤩🤩 | +| [1410. HTML 实体解析器](https://leetcode.cn/problems/html-entity-parser/) | [LeetCode 题解链接](https://leetcode.cn/problems/html-entity-parser/solutions/2538217/gong-shui-san-xie-jing-dian-zi-fu-chuan-rvdh3/) | 中等 | 🤩🤩🤩 | | [1441. 用栈操作构建数组](https://leetcode.cn/problems/build-an-array-with-stack-operations/) | [LeetCode 题解链接](https://leetcode.cn/problems/build-an-array-with-stack-operations/solution/by-ac_oier-q37s/) | 中等 | 🤩🤩🤩🤩 | | [1413. 逐步求和得到正数的最小值](https://leetcode.cn/problems/minimum-value-to-get-positive-step-by-step-sum/) | [LeetCode 题解链接](https://leetcode.cn/problems/minimum-value-to-get-positive-step-by-step-sum/solution/by-ac_oier-qo4e/) | 简单 | 🤩🤩🤩🤩 | | [1417. 重新格式化字符串](https://leetcode.cn/problems/reformat-the-string/) | [LeetCode 题解链接](https://leetcode.cn/problems/reformat-the-string/solution/by-ac_oier-uk8z/) | 简单 | 🤩🤩🤩🤩 | diff --git "a/Index/\351\223\276\350\241\250.md" "b/Index/\351\223\276\350\241\250.md" index b678eb27..d27e6ec8 100644 --- "a/Index/\351\223\276\350\241\250.md" +++ "b/Index/\351\223\276\350\241\250.md" @@ -28,6 +28,8 @@ | [817. 链表组件](https://leetcode.cn/problems/linked-list-components/) | [LeetCode 题解链接](https://leetcode.cn/problems/linked-list-components/solution/by-ac_oier-3gl5/) | 中等 | 🤩🤩🤩🤩 | | [1206. 设计跳表](https://leetcode.cn/problems/design-skiplist/) | [LeetCode 题解链接](https://leetcode.cn/problems/design-skiplist/solution/by-ac_oier-38rd/) | 困难 | 🤩🤩🤩🤩 | | [1600. 皇位继承顺序](https://leetcode-cn.com/problems/throne-inheritance/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/throne-inheritance/solution/gong-shui-san-xie-shi-yong-dan-xiang-lia-7t65/) | 中等 | 🤩🤩🤩 | +| [1669. 合并两个链表](https://leetcode.cn/problems/merge-in-between-linked-lists/) | [LeetCode 题解链接](https://leetcode.cn/problems/merge-in-between-linked-lists/solution/gong-shui-san-xie-jian-dan-lian-biao-ti-4k20i/) | 中等 | 🤩🤩🤩🤩 | +| [1670. 设计前中后队列](https://leetcode.cn/problems/design-front-middle-back-queue/) | [LeetCode 题解链接](https://leetcode.cn/problems/design-front-middle-back-queue/solutions/2544779/gong-shui-san-xie-qing-xi-gao-xiao-de-qu-o0eq/?envType=daily-question&envId=2023-11-28) | 中等 | 🤩🤩🤩 | | [剑指 Offer 06. 从尾到头打印链表](https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/) | [LeetCode 题解链接](https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/solution/by-ac_oier-3qsk/) | 简单 | 🤩🤩🤩🤩🤩 | | [剑指 Offer 22. 链表中倒数第k个节点](https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/solution/gong-shui-san-xie-yi-ti-san-jie-zhan-dui-w3rz/) | 简单 | 🤩🤩🤩🤩🤩 | | [剑指 Offer 24. 反转链表](https://leetcode.cn/problems/fan-zhuan-lian-biao-lcof/) | [LeetCode 题解链接](https://leetcode.cn/problems/fan-zhuan-lian-biao-lcof/solution/by-ac_oier-nqfc/) | 简单 | 🤩🤩🤩🤩🤩 | diff --git "a/Index/\351\230\237\345\210\227.md" "b/Index/\351\230\237\345\210\227.md" index 6bb953b2..cc0de3ec 100644 --- "a/Index/\351\230\237\345\210\227.md" +++ "b/Index/\351\230\237\345\210\227.md" @@ -4,5 +4,6 @@ | [649. Dota2 参议院](https://leetcode.cn/problems/dota2-senate/) | [LeetCode 题解链接](https://leetcode.cn/problems/dota2-senate/solutions/2402101/gong-shui-san-xie-jie-he-shu-ju-jie-gou-x581k/) | 中等 | 🤩🤩🤩🤩🤩 | | [1047. 删除字符串中的所有相邻重复项](https://leetcode-cn.com/problems/remove-all-adjacent-duplicates-in-string/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/remove-all-adjacent-duplicates-in-string/solution/cong-30-dao-100wu-chong-shi-xian-jie-jue-vkah/) | 简单 | 🤩🤩🤩🤩 | | [1190. 反转每对括号间的子串](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/gong-shui-san-xie-shi-yong-shuang-duan-d-r35q/) | 中等 | 🤩🤩🤩🤩🤩 | +| [1670. 设计前中后队列](https://leetcode.cn/problems/design-front-middle-back-queue/) | [LeetCode 题解链接](https://leetcode.cn/problems/design-front-middle-back-queue/solutions/2544779/gong-shui-san-xie-qing-xi-gao-xiao-de-qu-o0eq/?envType=daily-question&envId=2023-11-28) | 中等 | 🤩🤩🤩🤩🤩 | | [剑指 Offer II 041. 滑动窗口的平均值](https://leetcode.cn/problems/qIsx9U/) | [LeetCode 题解链接](https://leetcode.cn/problems/qIsx9U/solution/by-ac_oier-g5ha/) | 简单 | 🤩🤩🤩🤩 | diff --git "a/LeetCode/1401-1410/1410. HTML \345\256\236\344\275\223\350\247\243\346\236\220\345\231\250\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/1401-1410/1410. HTML \345\256\236\344\275\223\350\247\243\346\236\220\345\231\250\357\274\210\344\270\255\347\255\211\357\274\211.md" new file mode 100644 index 00000000..cba6c2d8 --- /dev/null +++ "b/LeetCode/1401-1410/1410. HTML \345\256\236\344\275\223\350\247\243\346\236\220\345\231\250\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -0,0 +1,202 @@ +### 题目描述 + +这是 LeetCode 上的 **[1410. HTML 实体解析器](https://leetcode.cn/problems/html-entity-parser/solutions/2538217/gong-shui-san-xie-jing-dian-zi-fu-chuan-rvdh3/)** ,难度为 **中等**。 + +Tag : 「模拟」、「哈希表」 + + + + +「HTML 实体解析器」 是一种特殊的解析器,它将 HTML 代码作为输入,并用字符本身替换掉所有这些特殊的字符实体。 + +HTML 里这些特殊字符和它们对应的字符实体包括: + +* 双引号:字符实体为 `"`,对应的字符是 `"`。 +* 单引号:字符实体为 `'`,对应的字符是 `'` 。 +* 与符号:字符实体为 `&`,对应对的字符是 `&` 。 +* 大于号:字符实体为 `>`,对应的字符是 `>`。 +* 小于号:字符实体为 `<`,对应的字符是 `<`。 +* 斜线号:字符实体为 `⁄`,对应的字符是 `/`。 + +给你输入字符串 `text`,请你实现一个 HTML 实体解析器,返回解析器解析后的结果。 + +示例 1: +``` +输入:text = "& is an HTML entity but &ambassador; is not." + +输出:"& is an HTML entity but &ambassador; is not." + +解释:解析器把字符实体 & 用 & 替换 +``` +示例 2: +``` +输入:text = "and I quote: "..."" + +输出:"and I quote: \"...\"" +``` +示例 3: +``` +输入:text = "Stay home! Practice on Leetcode :)" + +输出:"Stay home! Practice on Leetcode :)" +``` +示例 4: +``` +输入:text = "x > y && x < y is always false" + +输出:"x > y && x < y is always false" +``` +示例 5: +``` +输入:text = "leetcode.com⁄problemset⁄all" + +输出:"leetcode.com/problemset/all" +``` + +提示: +* $1 <= text.length <= 10^5$ +* 字符串可能包含 $256$ 个`ASCII` 字符中的任意字符。 + +--- + +### 模拟 + +每个特殊字符均以 `&` 开头,最长一个特殊字符为 `⁄`。 + +从前往后处理 `text`,若遇到 `&` 则往后读取最多 $6$ 个字符(中途遇到结束字符 `;` 则终止),若读取子串为特殊字符,将使用替换字符进行拼接,否则使用原字符进行拼接。 + +Java 代码: +```Java +class Solution { + public String entityParser(String text) { + Map map = new HashMap<>(){{ + put(""", "\""); + put("'", "'"); + put("&", "&"); + put(">", ">"); + put("<", "<"); + put("⁄", "/"); + }}; + int n = text.length(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; ) { + if (text.charAt(i) == '&') { + int j = i + 1; + while (j < n && j - i < 6 && text.charAt(j) != ';') j++; + String sub = text.substring(i, Math.min(j + 1, n)); + if (map.containsKey(sub)) { + sb.append(map.get(sub)); + i = j + 1; + continue; + } + } + sb.append(text.charAt(i++)); + } + return sb.toString(); + } +} +``` +C++ 代码: +```C++ +class Solution { +public: + string entityParser(string text) { + unordered_map entityMap = { + {""", "\""}, + {"'", "'"}, + {"&", "&"}, + {">", ">"}, + {"<", "<"}, + {"⁄", "/"} + }; + int n = text.length(); + string ans = ""; + for (int i = 0; i < n; ) { + if (text[i] == '&') { + int j = i + 1; + while (j < n && j - i < 6 && text[j] != ';') j++; + string sub = text.substr(i, min(j + 1, n) - i); + if (entityMap.find(sub) != entityMap.end()) { + ans += entityMap[sub]; + i = j + 1; + continue; + } + } + ans += text[i++]; + } + return ans; + } +}; +``` +Python 代码: +```Python +class Solution: + def entityParser(self, text: str) -> str: + entity_map = { + """: "\"", + "'": "'", + "&": "&", + ">": ">", + "<": "<", + "⁄": "/" + } + i, n = 0, len(text) + ans = "" + while i < n: + if text[i] == '&': + j = i + 1 + while j < n and j - i < 6 and text[j] != ';': + j += 1 + sub = text[i:min(j + 1, n)] + if sub in entity_map: + ans += entity_map[sub] + i = j + 1 + continue + ans += text[i] + i += 1 + return ans +``` +TypeScript 代码: +```TypeScript +function entityParser(text: string): string { + const entityMap: { [key: string]: string } = { + """: "\"", + "'": "'", + "&": "&", + ">": ">", + "<": "<", + "⁄": "/" + }; + const n = text.length; + let ans = ""; + for (let i = 0; i < n; ) { + if (text[i] == '&') { + let j = i + 1; + while (j < n && j - i < 6 && text[j] != ';') j++; + const sub = text.substring(i, Math.min(j + 1, n)); + if (entityMap[sub]) { + ans += entityMap[sub]; + i = j + 1; + continue; + } + } + ans += text[i++]; + } + return ans; +}; +``` +* 时间复杂度:$O(n \times K)$,其中 $K = 6$ 为最大特殊字符长度 +* 空间复杂度:$O(C)$,一个固定大小的哈希表 + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.1410` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 + diff --git "a/LeetCode/1451-1460/1457. \344\272\214\345\217\211\346\240\221\344\270\255\347\232\204\344\274\252\345\233\236\346\226\207\350\267\257\345\276\204\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/1451-1460/1457. \344\272\214\345\217\211\346\240\221\344\270\255\347\232\204\344\274\252\345\233\236\346\226\207\350\267\257\345\276\204\357\274\210\344\270\255\347\255\211\357\274\211.md" new file mode 100644 index 00000000..bae70e1e --- /dev/null +++ "b/LeetCode/1451-1460/1457. \344\272\214\345\217\211\346\240\221\344\270\255\347\232\204\344\274\252\345\233\236\346\226\207\350\267\257\345\276\204\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -0,0 +1,159 @@ +### 题目描述 + +这是 LeetCode 上的 **[1457. 二叉树中的伪回文路径](https://leetcode.cn/problems/pseudo-palindromic-paths-in-a-binary-tree/solutions/2540912/gong-shui-san-xie-gao-xiao-ji-jian-de-we-f2gb/)** ,难度为 **中等**。 + +Tag : 「DFS」、「位运算」 + + + +给你一棵二叉树,每个节点的值为 `1` 到 `9` 。 + +我们称二叉树中的一条路径是 「伪回文」的,当它满足:路径经过的所有节点值的排列中,存在一个回文序列。 + +请你返回从根到叶子节点的所有路径中伪回文路径的数目。 + +示例 1: +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/05/23/palindromic_paths_1.png) + +``` +输入:root = [2,3,1,3,1,null,1] + +输出:2 + +解释:上图为给定的二叉树。总共有 3 条从根到叶子的路径:红色路径 [2,3,3] ,绿色路径 [2,1,1] 和路径 [2,3,1] 。 + 在这些路径中,只有红色和绿色的路径是伪回文路径,因为红色路径 [2,3,3] 存在回文排列 [3,2,3] ,绿色路径 [2,1,1] 存在回文排列 [1,2,1] 。 +``` +示例 2: +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/05/23/palindromic_paths_2.png) +``` +输入:root = [2,1,1,1,3,null,null,null,null,null,1] + +输出:1 + +解释:上图为给定二叉树。总共有 3 条从根到叶子的路径:绿色路径 [2,1,1] ,路径 [2,1,3,1] 和路径 [2,1] 。 + 这些路径中只有绿色路径是伪回文路径,因为 [2,1,1] 存在回文排列 [1,2,1] 。 +``` +示例 3: +``` +输入:root = [9] + +输出:1 +``` + +提示: +* 给定二叉树的节点数目在范围 $[1, 10^5]$ 内 +* $1 <= Node.val <= 9$ + +--- + +### DFS + 位运算 + +“伪回文”是指能够通过重新排列变成“真回文”,真正的回文串只有两种情况: + +* 长度为偶数,即出现次数为奇数的字符个数为 $0$ 个 +* 长度为奇数,即出现次数为奇数的字符个数为 $1$ 个(位于中间) + +因此,**我们只关心路径中各个字符(数字 `0-9`)出现次数的奇偶性,若路径中所有字符出现次数均为偶数,或仅有一个字符出现次数为奇数,那么该路径满足要求**。 + +节点值范围为 $[1, 9]$,除了使用固定大小的数组进行词频统计以外,还可以使用一个 `int` 类型的变量 `cnt` 来统计各数值的出现次数奇偶性:若 $cnt$ 的第 $k$ 位为 $1$,说明数值 $k$ 的出现次数为奇数,否则说明数值 $k$ 出现次数为偶数或没出现过,两者是等价的。 + +例如 $cnt = (0001010)_2$ 代表数值 $1$ 和数值 $3$ 出现次数为奇数次,其余数值没出现过或出现次数为偶数次。 + +翻转一个二进制数字中的某一位可使用「异或」操作,具体操作位 `cnt ^= 1 << k`。 + +判断是否最多只有一个字符出现奇数次的操作,也就是判断一个二进制数字是为全为 $0$ 或仅有一位 $1$,可配合 `lowbit` 来做,若 `cnt` 与 `lowbit(cnt) = cnt & -cnt` 相等,说明满足要求。 + +考虑到对 `lowbit(x) = x & -x` 不熟悉的同学,这里再做简单介绍:*`lowbit(x)` 表示 `x` 的二进制表示中最低位的 $1$ 所在的位置对应的值*,即仅保留从最低位起的第一个 $1$,其余位均以 $0$ 填充: +* `x = 6`,其二进制表示为 $(110)_2$,那么 $lowbit(6) = (010)_2 = 2$ +* `x = 12`,其二进制表示为 $(1100)_2$,那么 $lowbit(12) = (100)_2 = 4$ + +Java 代码: + +```Java +class Solution { + int ans = 0; + public int pseudoPalindromicPaths (TreeNode root) { + dfs(root, 0); + return ans; + } + void dfs(TreeNode root, int cnt) { + if (root.left == null && root.right == null) { + cnt ^= 1 << root.val; + if (cnt == (cnt & -cnt)) ans++; + return ; + } + if (root.left != null) dfs(root.left, cnt ^ (1 << root.val)); + if (root.right != null) dfs(root.right, cnt ^ (1 << root.val)); + } +} +``` +C++ 代码: +```C++ +class Solution { +public: + int ans; + int pseudoPalindromicPaths(TreeNode* root) { + dfs(root, 0); + return ans; + } + void dfs(TreeNode* root, int cnt) { + if (!root->left && !root->right) { + cnt ^= 1 << root->val; + if (cnt == (cnt & -cnt)) ans++; + return; + } + if (root->left) dfs(root->left, cnt ^ (1 << root->val)); + if (root->right) dfs(root->right, cnt ^ (1 << root->val)); + } +}; +``` +Python 代码: +```Python +class Solution: + def pseudoPalindromicPaths (self, root: Optional[TreeNode]) -> int: + ans = 0 + def dfs(root, cnt): + nonlocal ans + if not root.left and not root.right: + cnt ^= 1 << root.val + ans += 1 if cnt == (cnt & -cnt) else 0 + return + if root.left: + dfs(root.left, cnt ^ (1 << root.val)) + if root.right: + dfs(root.right, cnt ^ (1 << root.val)) + dfs(root, 0) + return ans +``` +TypeScript 代码: +```TypeScript +function pseudoPalindromicPaths (root: TreeNode | null): number { + let ans = 0; + const dfs = function (root: TreeNode, cnt: number): void { + if (root.left == null && root.right == null) { + cnt ^= 1 << root.val; + if (cnt == (cnt & -cnt)) ans++; + return ; + } + if (root.left) dfs(root.left, cnt ^ (1 << root.val)); + if (root.right) dfs(root.right, cnt ^ (1 << root.val)); + } + dfs(root, 0); + return ans; +}; +``` +* 时间复杂度:$O(n)$ +* 空间复杂度:$O(\log{n})$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.1457` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 + diff --git "a/LeetCode/1661-1670/1669. \345\220\210\345\271\266\344\270\244\344\270\252\351\223\276\350\241\250\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/1661-1670/1669. \345\220\210\345\271\266\344\270\244\344\270\252\351\223\276\350\241\250\357\274\210\344\270\255\347\255\211\357\274\211.md" index bd52fd1b..08d3762b 100644 --- "a/LeetCode/1661-1670/1669. \345\220\210\345\271\266\344\270\244\344\270\252\351\223\276\350\241\250\357\274\210\344\270\255\347\255\211\357\274\211.md" +++ "b/LeetCode/1661-1670/1669. \345\220\210\345\271\266\344\270\244\344\270\252\351\223\276\350\241\250\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -1,8 +1,8 @@ ### 题目描述 -这是 LeetCode 上的 **[1669. 合并两个链表](/)** ,难度为 **中等**。 +这是 LeetCode 上的 **[1669. 合并两个链表](https://leetcode.cn/problems/merge-in-between-linked-lists/solutions/2538688/gong-shui-san-xie-jian-dan-lian-biao-ti-4k20i/)** ,难度为 **中等**。 -Tag : 「链表」、「模拟」 +Tag : 「链表」 diff --git "a/LeetCode/1661-1670/1670. \350\256\276\350\256\241\345\211\215\344\270\255\345\220\216\351\230\237\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/1661-1670/1670. \350\256\276\350\256\241\345\211\215\344\270\255\345\220\216\351\230\237\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" new file mode 100644 index 00000000..0be805ec --- /dev/null +++ "b/LeetCode/1661-1670/1670. \350\256\276\350\256\241\345\211\215\344\270\255\345\220\216\351\230\237\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -0,0 +1,459 @@ +### 题目描述 + +这是 LeetCode 上的 **[1670. 设计前中后队列](https://leetcode.cn/problems/design-front-middle-back-queue/solutions/2544779/gong-shui-san-xie-qing-xi-gao-xiao-de-qu-o0eq/)** ,难度为 **中等**。 + +Tag : 「数据结构」、「双端队列」、「队列」、「链表」 + + + +请你设计一个队列,支持在前,中,后三个位置的 `push` 和 `pop` 操作。 + +请你完成 `FrontMiddleBack` 类: + +* `FrontMiddleBack()` 初始化队列。 +* `void pushFront(int val)` 将 `val` 添加到队列的 最前面 。 +* `void pushMiddle(int val)` 将 `val` 添加到队列的 正中间 。 +* `void pushBack(int val)` 将 `val` 添加到队里的 最后面 。 +* `int popFront()` 将最前面的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 `-1`。 +* `int popMiddle()` 将正中间的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 `-1`。 +* `int popBack()` 将 最后面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 `-1`。 + +请注意当有 两个 中间位置的时候,选择靠前面的位置进行操作。比方说: + +* 将 `6` 添加到 `[1, 2, 3, 4, 5]` 的中间位置,结果数组为 `[1, 2, 6, 3, 4, 5]`。 +* 从 `[1, 2, 3, 4, 5, 6]` 的中间位置弹出元素,返回 `3`,数组变为 `[1, 2, 4, 5, 6]`。 + +示例 1: +``` +输入: +["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"] +[[], [1], [2], [3], [4], [], [], [], [], []] + +输出: +[null, null, null, null, null, 1, 3, 4, 2, -1] + +解释: +FrontMiddleBackQueue q = new FrontMiddleBackQueue(); +q.pushFront(1); // [1] +q.pushBack(2); // [1, 2] +q.pushMiddle(3); // [1, 3, 2] +q.pushMiddle(4); // [1, 4, 3, 2] +q.popFront(); // 返回 1 -> [4, 3, 2] +q.popMiddle(); // 返回 3 -> [4, 2] +q.popMiddle(); // 返回 4 -> [2] +q.popBack(); // 返回 2 -> [] +q.popFront(); // 返回 -1 -> [] (队列为空) +``` + +提示: +* $1 <= val <= 10^9$ +* 最多调用 $1000$ 次 `pushFront`, `pushMiddle`, `pushBack`, `popFront`, `popMiddle` 和 `popBack`。 + +--- + +### 双端队列 + +只要求在头部或尾部高效插入/弹出元素的话,容易联想到双端队列。 + +还需要考虑往中间插入/弹出元素的话,会想到使用两个双端队列。 + +将两个双端队列分别称为 `l` 和 `r`,把 `l` 和 `r` 拼接起来就是完整元素列表: + +![](https://pic.leetcode.cn/1701131956-KvABan-image.png) + +由于双端队列本身支持 $O(1)$ 首尾操作,问题的关键在于如何确保涉及 `Middle` 操作的高效性。 + +我们可以设计一个 `update` 方法,用于确保两队列的相对平衡: + +* 当元素总个数为偶数时,确保两队列元素相等 +* 当元素总个数为奇数时,确保 `r` 队列比 `l` 队列元素多一个 + +如此一来,当我们需要往 `Middle` 插入元素时,始终往 `l` 的尾部插入即可;而当需要读取 `Middle` 位置元素时,根据两队列的元素个数关系决定是从 `l` 的尾部还是从 `r` 的头部取元素。 + +以下是对上述代码中几个操作的简短实现说明: + +* `pushFront`:将元素添加到 `l` 队列的头部,调用 `update` 保持队列平衡 +* `pushMiddle`:将元素添加到 `l` 队列的尾部,调用 `update` 保持队列平衡 +* `pushBack`:将元素添加到 `r` 队列的尾部,调用 `update` 保持队列平衡 +* `popFront`:若 `l` 队列不为空,从 `l` 队列的头部弹出一个元素;否则,从 `r` 队列的头部弹出一个元素(当且仅当元素个数为 $1$ 时,队列 `l` 为空,唯一元素在队列 `r` 中),调用 `update` 保持队列平衡 +* `popMiddle`:若 `l` 队列和 `r` 队列的大小相等,则从 `l` 队列的尾部弹出一个元素;否则,从 `r` 队列的头部弹出一个元素。调用 `update` 保持队列平衡 +* `popBack`:从 `r` 队列的尾部弹出一个元素,调用 `update` 保持队列平衡 + +双端队列的实现,可通过「数组 + 首尾坐标指针」来实现。为方便大家理清脉络,先使用语言自带的 `Deque` 实现一版。 + +Java 代码(`Deque` 版): +```Java +class FrontMiddleBackQueue { + Deque l = new ArrayDeque<>(1010), r = new ArrayDeque<>(1010); + public void pushFront(int val) { + l.addFirst(val); + update(); + } + public void pushMiddle(int val) { + l.addLast(val); + update(); + } + public void pushBack(int val) { + r.addLast(val); + update(); + } + public int popFront() { + if (l.size() + r.size() == 0) return -1; + int ans = l.size() != 0 ? l.pollFirst() : r.pollFirst(); + update(); + return ans; + } + public int popMiddle() { + if (l.size() + r.size() == 0) return -1; + int ans = l.size() == r.size() ? l.pollLast() : r.pollFirst(); + update(); + return ans; + } + public int popBack() { + if (l.size() + r.size() == 0) return -1; + int ans = r.pollLast(); + update(); + return ans; + } + void update() { + while (l.size() > r.size()) r.addFirst(l.pollLast()); + while (r.size() - l.size() > 1) l.addLast(r.pollFirst()); + } +} +``` + +看过 `Deque` 实现版本,考虑如何使用数组实现。 + +各类操作的总调用次数最多为 $1000$ 次,我们可创建大小为 $2010$ 的数组,并从下标 $1010$(接近中间位置)开始进行存储,这样无论是从前还是往后存数都不会越界。 + +使用 `lhe` 和 `lta` 代表队列 `l` 的头部和尾部坐标,使用 `rhe` 和 `rta` 代表队列 `r` 的头部和尾部坐标,所有坐标初始值均为 $1100$。 + +需要注意的是,`ta`(无论是 `lta` 还是 `rta`)是严格指向尾部,因此如果要往尾部插数的话,需要先对指针自增(移到下一个空闲位置),再赋值;而 `he`(无论是 `lhe` 还是 `rhe`)是指向实际队列头部的前一位置,需要先赋值再前移。当 `he = ta` 代表队列为空。 + +Java 代码(纯数组版): + +```Java +class FrontMiddleBackQueue { + int[] l = new int[2010], r = new int[2010]; + int lhe = 1010, lta = 1010, rhe = 1010, rta = 1010; + public void pushFront(int val) { + l[lhe--] = val; + update(); + } + public void pushMiddle(int val) { + l[++lta] = val; + update(); + } + public void pushBack(int val) { + r[++rta] = val; + update(); + } + public int popFront() { + if (getSize(lhe, lta) == 0 && getSize(rhe, rta) == 0) return -1; + int ans = getSize(lhe, lta) != 0 ? l[++lhe] : r[++rhe]; + update(); + return ans; + } + public int popMiddle() { + if (getSize(lhe, lta) + getSize(rhe, rta) == 0) return -1; + int ans = getSize(lhe, lta) == getSize(rhe, rta) ? l[lta--] : r[++rhe]; + update(); + return ans; + } + public int popBack() { + if (getSize(lhe, lta) == 0 && getSize(rhe, rta) == 0) return -1; + int ans = r[rta--]; + update(); + return ans; + } + int getSize(int he, int ta) { + return ta - he; + } + void update() { + while (getSize(lhe, lta) > getSize(rhe, rta)) r[rhe--] = l[lta--]; + while (getSize(rhe, rta) - getSize(lhe, lta) > 1) l[++lta] = r[++rhe]; + } +} +``` +C++ 代码: +```C++ +class FrontMiddleBackQueue { +public: + int l[2010], r[2010], lhe = 1010, lta = 1010, rhe = 1010, rta = 1010; + void pushFront(int val) { + l[lhe--] = val; + update(); + } + void pushMiddle(int val) { + l[++lta] = val; + update(); + } + void pushBack(int val) { + r[++rta] = val; + update(); + } + int popFront() { + if (getSize(lhe, lta) == 0 && getSize(rhe, rta) == 0) return -1; + int ans = getSize(lhe, lta) != 0 ? l[++lhe] : r[++rhe]; + update(); + return ans; + } + int popMiddle() { + if (getSize(lhe, lta) == 0 && getSize(rhe, rta) == 0) return -1; + int ans = getSize(lhe, lta) == getSize(rhe, rta) ? l[lta--] : r[++rhe]; + update(); + return ans; + } + int popBack() { + if (getSize(lhe, lta) == 0 && getSize(rhe, rta) == 0) return -1; + int ans = r[rta--]; + update(); + return ans; + } + int getSize(int he, int ta) { + return ta - he; + } + void update() { + while (getSize(lhe, lta) > getSize(rhe, rta)) r[rhe--] = l[lta--]; + while (getSize(rhe, rta) - getSize(lhe, lta) > 1) l[++lta] = r[++rhe]; + } +}; +``` +Python 代码: +```Python +class FrontMiddleBackQueue: + def __init__(self): + self.l, self.r = [0] * 2010, [0] * 2010 + self.r = [0] * 2010 + self.lhe, self.lta, self.rhe, self.rta = 1010, 1010, 1010, 1010 + + def pushFront(self, val: int) -> None: + self.l[self.lhe] = val + self.lhe -= 1 + self.update() + + def pushMiddle(self, val: int) -> None: + self.lta += 1 + self.l[self.lta] = val + self.update() + + def pushBack(self, val: int) -> None: + self.rta += 1 + self.r[self.rta] = val + self.update() + + def popFront(self) -> int: + if self.getSize(self.lhe, self.lta) + self.getSize(self.rhe, self.rta) == 0: + return -1 + if self.getSize(self.lhe, self.lta) != 0: + self.lhe += 1 + ans = self.l[self.lhe] + else: + self.rhe += 1 + ans = self.r[self.rhe] + self.update() + return ans + + def popMiddle(self) -> int: + if self.getSize(self.lhe, self.lta) + self.getSize(self.rhe, self.rta) == 0: + return -1 + if self.getSize(self.lhe, self.lta) == self.getSize(self.rhe, self.rta): + ans = self.l[self.lta] + self.lta -= 1 + else: + self.rhe += 1 + ans = self.r[self.rhe] + self.update() + return ans + + def popBack(self) -> int: + if self.getSize(self.lhe, self.lta) + self.getSize(self.rhe, self.rta) == 0: + return -1 + ans = self.r[self.rta] + self.rta -= 1 + self.update() + return ans + + def getSize(self, he: int, ta: int) -> int: + return ta - he + + def update(self) -> None: + while self.getSize(self.lhe, self.lta) > self.getSize(self.rhe, self.rta): + self.r[self.rhe] = self.l[self.lta] + self.rhe -= 1 + self.lta -= 1 + while self.getSize(self.rhe, self.rta) - self.getSize(self.lhe, self.lta) > 1: + self.lta += 1 + self.rhe += 1 + self.l[self.lta] = self.r[self.rhe] +``` +TypeScript 代码: +```TypeScript +class FrontMiddleBackQueue { + private l: number[]; + private r: number[]; + private lhe: number; + private lta: number; + private rhe: number; + private rta: number; + constructor() { + this.l = Array(2010).fill(0), this.r = Array(2010).fill(0); + this.lhe = 1010, this.lta = 1010, this.rhe = 1010, this.rta = 1010; + } + pushFront(val: number): void { + this.l[this.lhe--] = val; + this.update(); + } + pushMiddle(val: number): void { + this.l[++this.lta] = val; + this.update(); + } + pushBack(val: number): void { + this.r[++this.rta] = val; + this.update(); + } + popFront(): number { + if (this.getSize(this.lhe, this.lta) + this.getSize(this.rhe, this.rta) == 0) return -1; + const ans = this.getSize(this.lhe, this.lta) != 0 ? this.l[++this.lhe] : this.r[++this.rhe]; + this.update(); + return ans; + } + popMiddle(): number { + if (this.getSize(this.lhe, this.lta) + this.getSize(this.rhe, this.rta) == 0) return -1; + const ans = this.getSize(this.lhe, this.lta) == this.getSize(this.rhe, this.rta) ? this.l[this.lta--] : this.r[++this.rhe]; + this.update(); + return ans; + } + popBack(): number { + if (this.getSize(this.lhe, this.lta) + this.getSize(this.rhe, this.rta) == 0) return -1; + const ans = this.r[this.rta--]; + this.update(); + return ans; + } + private getSize(he: number, ta: number): number { + return ta - he; + } + private update(): void { + while (this.getSize(this.lhe, this.lta) > this.getSize(this.rhe, this.rta)) this.r[this.rhe--] = this.l[this.lta--]; + while (this.getSize(this.rhe, this.rta) - this.getSize(this.lhe, this.lta) > 1) this.l[++this.lta] = this.r[++this.rhe]; + } +} +``` +* 时间复杂度:所有操作复杂度均为 $O(1)$ +* 空间复杂度:$O(n)$ + +--- + +### 进阶 + +更进一步,使用双向链表并与实现 `update` 类似效果,维护 `Middle` 位置的元素节点,同样可实现 $O(1)$ 各项操作,你能完成吗? + +与纯数组版相比,使用链表好处在于可严格按需创建。 + +```Java +class Node { + Node prev, next; + int val; + Node (int _val) { + val = _val; + } +} +class FrontMiddleBackQueue { + Node he, ta, mid; + int lsz, rsz; + public FrontMiddleBackQueue() { + he = new Node(-1); ta = new Node(-1); + he.next = ta; ta.prev = he; + mid = ta; + lsz = rsz = 0; + } + public void pushFront(int val) { + Node cur = new Node(val); + cur.next = he.next; + cur.prev = he; + he.next.prev = cur; + he.next = cur; + lsz++; + update(); + } + public void pushMiddle(int val) { + Node cur = new Node(val); + cur.next = mid; + cur.prev = mid.prev; + mid.prev.next = cur; + mid.prev = cur; + lsz++; + update(); + } + public void pushBack(int val) { + Node cur = new Node(val); + cur.next = ta; + cur.prev = ta.prev; + ta.prev.next = cur; + ta.prev = cur; + rsz++; + update(); + } + public int popFront() { + if (lsz + rsz == 0) return -1; + int ans = he.next.val; + he.next.next.prev = he; + he.next = he.next.next; + lsz--; + update(); + return ans; + } + public int popMiddle() { + if (lsz + rsz == 0) return -1; + Node realMid = null; + if (lsz == rsz) { + realMid = mid.prev; + lsz--; + } else { + realMid = mid; + mid = mid.next; + rsz--; + } + int ans = realMid.val; + realMid.prev.next = realMid.next; + realMid.next.prev = realMid.prev; + realMid = realMid.next; + update(); + return ans; + } + public int popBack() { + if (lsz + rsz == 0) return -1; + int ans = ta.prev.val; + ta.prev.prev.next = ta; + ta.prev = ta.prev.prev; + rsz--; + update(); + return ans; + } + void update() { + while (lsz > rsz) { + mid = mid.prev; + lsz--; rsz++; + } + while (rsz - lsz > 1) { + mid = mid.next; + lsz++; rsz--; + } + if (lsz + rsz == 1) mid = ta.prev; + if (lsz + rsz == 0) mid = ta; + } +} +``` + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.1670` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 + diff --git "a/LeetCode/2211-2220/2216. \347\276\216\345\214\226\346\225\260\347\273\204\347\232\204\346\234\200\345\260\221\345\210\240\351\231\244\346\225\260\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/2211-2220/2216. \347\276\216\345\214\226\346\225\260\347\273\204\347\232\204\346\234\200\345\260\221\345\210\240\351\231\244\346\225\260\357\274\210\344\270\255\347\255\211\357\274\211.md" index cfb148c0..0683fde5 100644 --- "a/LeetCode/2211-2220/2216. \347\276\216\345\214\226\346\225\260\347\273\204\347\232\204\346\234\200\345\260\221\345\210\240\351\231\244\346\225\260\357\274\210\344\270\255\347\255\211\357\274\211.md" +++ "b/LeetCode/2211-2220/2216. \347\276\216\345\214\226\346\225\260\347\273\204\347\232\204\346\234\200\345\260\221\345\210\240\351\231\244\346\225\260\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -42,9 +42,9 @@ Tag : 「模拟」 ### 模拟 -使用变量 `cnt` 代表已删除的元素个数,由于每次删除元素,剩余元素都会往前移动,因此当前下标为 $i - cnt$。 +使用变量 `cnt` 代表已删除的元素个数,由于每次删除元素,剩余元素都会往前移动,因此遍历过程中,当前下标为 $i - cnt$。 -处理 `nums` 过程中,若当前下标为偶数,且与下一位置元素相同,那么当前元素需被删除,令 `cnt` 自增。 +若当前下标为偶数,且与下一位置元素相同,那么当前元素需被删除,令 `cnt` 自增。 最终数组长度为 $n - cnt$,若长度为奇数,需要再额外删除结尾元素(`cnt` 再加一),否则 `cnt` 即为答案。 diff --git "a/LeetCode/2331-2340/2336. \346\227\240\351\231\220\351\233\206\344\270\255\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/2331-2340/2336. \346\227\240\351\231\220\351\233\206\344\270\255\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227\357\274\210\344\270\255\347\255\211\357\274\211.md" new file mode 100644 index 00000000..dfbf2e11 --- /dev/null +++ "b/LeetCode/2331-2340/2336. \346\227\240\351\231\220\351\233\206\344\270\255\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -0,0 +1,158 @@ +### 题目描述 + +这是 LeetCode 上的 **[2336. 无限集中的最小数字](https://leetcode.cn/problems/smallest-number-in-infinite-set/solutions/2546157/gong-shui-san-xie-rong-yi-you-gao-xiao-d-431o/)** ,难度为 **中等**。 + +Tag : 「优先队列(堆)」、「哈希表」 + + + +现有一个包含所有正整数的集合 $[1, 2, 3, 4, 5, ...]$ 。 + +实现 `SmallestInfiniteSet` 类: + +* `SmallestInfiniteSet()` 初始化 `SmallestInfiniteSet` 对象以包含所有正整数。 +* `int popSmallest()` 移除并返回该无限集中的最小整数。 +* `void addBack(int num)` 如果正整数 `num` 不存在于无限集中,则将一个 `num` 添加到该无限集中。 + +示例: +``` +输入 +["SmallestInfiniteSet", "addBack", "popSmallest", "popSmallest", "popSmallest", "addBack", "popSmallest", "popSmallest", "popSmallest"] +[[], [2], [], [], [], [1], [], [], []] + +输出 +[null, null, 1, 2, 3, null, 1, 4, 5] + +解释 +SmallestInfiniteSet smallestInfiniteSet = new SmallestInfiniteSet(); +smallestInfiniteSet.addBack(2); // 2 已经在集合中,所以不做任何变更。 +smallestInfiniteSet.popSmallest(); // 返回 1 ,因为 1 是最小的整数,并将其从集合中移除。 +smallestInfiniteSet.popSmallest(); // 返回 2 ,并将其从集合中移除。 +smallestInfiniteSet.popSmallest(); // 返回 3 ,并将其从集合中移除。 +smallestInfiniteSet.addBack(1); // 将 1 添加到该集合中。 +smallestInfiniteSet.popSmallest(); // 返回 1 ,因为 1 在上一步中被添加到集合中, + // 且 1 是最小的整数,并将其从集合中移除。 +smallestInfiniteSet.popSmallest(); // 返回 4 ,并将其从集合中移除。 +smallestInfiniteSet.popSmallest(); // 返回 5 ,并将其从集合中移除。 +``` + +提示: +* $1 <= num <= 1000$ +* 最多调用 `popSmallest` 和 `addBack` 方法 共计 $1000$ 次 + +--- + +### 优先队列(小根堆)+ 哈希表 + +使用 `idx` 代表顺序弹出的集合左边界,$[idx, +\infty]$ 范围内的数均为待弹出,起始有 $idx = 1$。 + +考虑当调用 `addBack` 往集合添加数值 `x` 时,该如何处理: + +* $x \geq idx$:数值本身就存在于集合中,忽略该添加操作; +* $x = idx - 1$:数值刚好位于边界左侧,更新 $idx = idx - 1$; +* $x < idx - 1$:考虑将数值添加到某个容器中,该容器支持返回最小值,容易联想到“小根堆”;但小根堆并没有“去重”功能,为防止重复弹出,还需额外使用“哈希表”来记录哪些元素在堆中。 + +该做法本质上将集合分成两类:一类是从 `idx` 到正无穷的连续段,对此类操作的复杂度为 $O(1)$;一类是比 `idx` 要小的离散类数集,对该类操作复杂度为 $O(\log{n})$,其中 $n$ 为调用 `addBack` 的最大次数。 + +Java 代码: +```Java +class SmallestInfiniteSet { + boolean[] vis = new boolean[1010]; + PriorityQueue q = new PriorityQueue<>((a,b)->a-b); + int idx = 1; + public int popSmallest() { + int ans = -1; + if (!q.isEmpty()) { + ans = q.poll(); + vis[ans] = false; + } else { + ans = idx++; + } + return ans; + } + public void addBack(int x) { + if (x >= idx || vis[x]) return ; + if (x == idx - 1) { + idx--; + } else { + q.add(x); + vis[x] = true; + } + } +} +``` +C++ 代码: +```C++ +class SmallestInfiniteSet { +public: + vector vis; + priority_queue, greater> q; + int idx; + SmallestInfiniteSet() : idx(1) { + vis.resize(1010, false); + } + int popSmallest() { + int ans = -1; + if (!q.empty()) { + ans = q.top(); + q.pop(); + vis[ans] = false; + } else { + ans = idx++; + } + return ans; + } + void addBack(int x) { + if (x >= idx || vis[x]) return; + if (x == idx - 1) { + idx--; + } else { + q.push(x); + vis[x] = true; + } + } +}; + +``` +Python 代码: +```Python +class SmallestInfiniteSet: + def __init__(self): + self.vis = [False] * 1010 + self.q = [] + self.idx = 1 + + def popSmallest(self): + ans = -1 + if self.q: + ans = heapq.heappop(self.q) + self.vis[ans] = False + else: + ans = self.idx + self.idx += 1 + return ans + + def addBack(self, x): + if x >= self.idx or self.vis[x]: + return + if x == self.idx - 1: + self.idx -= 1 + else: + heapq.heappush(self.q, x) + self.vis[x] = True +``` +* 时间复杂度:插入和取出的最坏复杂度为 $O(\log{n})$ +* 空间复杂度:$O(n)$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.2336` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 + diff --git "a/LeetCode/2821-2830/2824. \347\273\237\350\256\241\345\222\214\345\260\217\344\272\216\347\233\256\346\240\207\347\232\204\344\270\213\346\240\207\345\257\271\346\225\260\347\233\256\357\274\210\347\256\200\345\215\225\357\274\211.md" "b/LeetCode/2821-2830/2824. \347\273\237\350\256\241\345\222\214\345\260\217\344\272\216\347\233\256\346\240\207\347\232\204\344\270\213\346\240\207\345\257\271\346\225\260\347\233\256\357\274\210\347\256\200\345\215\225\357\274\211.md" new file mode 100644 index 00000000..550ba496 --- /dev/null +++ "b/LeetCode/2821-2830/2824. \347\273\237\350\256\241\345\222\214\345\260\217\344\272\216\347\233\256\346\240\207\347\232\204\344\270\213\346\240\207\345\257\271\346\225\260\347\233\256\357\274\210\347\256\200\345\215\225\357\274\211.md" @@ -0,0 +1,220 @@ +### 题目描述 + +这是 LeetCode 上的 **[2824. 统计和小于目标的下标对数目](https://leetcode.cn/problems/count-pairs-whose-sum-is-less-than-target/solutions/2539761/gong-shui-san-xie-xiang-jie-zuo-zhao-you-1yji/)** ,难度为 **简单**。 + +Tag : 「排序」、「二分」、「双指针」 + + + +给你一个下标从 `0` 开始长度为 `n` 的整数数组 `nums` 和一个整数 `target`,请你返回满足 `0 <= i < j < n` 且 `nums[i] + nums[j] < target` 的下标对 $(i, j)$ 的数目。 + +示例 1: +``` +输入:nums = [-1,1,2,3,1], target = 2 + +输出:3 + +解释:总共有 3 个下标对满足题目描述: +- (0, 1) ,0 < 1 且 nums[0] + nums[1] = 0 < target +- (0, 2) ,0 < 2 且 nums[0] + nums[2] = 1 < target +- (0, 4) ,0 < 4 且 nums[0] + nums[4] = 0 < target +注意 (0, 3) 不计入答案因为 nums[0] + nums[3] 不是严格小于 target 。 +``` +示例 2: +``` +输入:nums = [-6,2,5,-2,-7,-1,3], target = -2 + +输出:10 + +解释:总共有 10 个下标对满足题目描述: +- (0, 1) ,0 < 1 且 nums[0] + nums[1] = -4 < target +- (0, 3) ,0 < 3 且 nums[0] + nums[3] = -8 < target +- (0, 4) ,0 < 4 且 nums[0] + nums[4] = -13 < target +- (0, 5) ,0 < 5 且 nums[0] + nums[5] = -7 < target +- (0, 6) ,0 < 6 且 nums[0] + nums[6] = -3 < target +- (1, 4) ,1 < 4 且 nums[1] + nums[4] = -5 < target +- (3, 4) ,3 < 4 且 nums[3] + nums[4] = -9 < target +- (3, 5) ,3 < 5 且 nums[3] + nums[5] = -3 < target +- (4, 5) ,4 < 5 且 nums[4] + nums[5] = -8 < target +- (4, 6) ,4 < 6 且 nums[4] + nums[6] = -4 < target +``` + +提示: +* $1 <= nums.length = n <= 50$ +* $-50 <= nums[i], target <= 50$ + +--- + +### 基本分析 + +为了方便,先对 `nums` 进行排序。 + +当 `nums` 有了有序特性后,剩下的便是「遍历右端点,在右端点左侧找最大合法左端点」或「遍历左端点,在左端点右侧找最大合法右端点」过程。 + +--- + +### 排序 + 二分 + +这是一种「遍历右端点,在右端点左侧找最大合法左端点」做法。 + +遍历右端点 `i`,然后在 $[0, i - 1]$ 范围内进行二分,找到最大的满足 $nums[j] + nums[i] < target$ 的位置 `j`。 + +若存在这样左端点 `j`,说明以 $nums[i]$ 为右端点时,共有 $j + 1$ 个(范围为 $[0, j]$ )个合法左端点,需要被统计。 + +Java 代码: + +```Java +class Solution { + public int countPairs(List nums, int target) { + Collections.sort(nums); + int n = nums.size(), ans = 0; + for (int i = 1; i < n; i++) { + int l = 0, r = i - 1; + while (l < r) { + int mid = l + r + 1 >> 1; + if (nums.get(mid) + nums.get(i) < target) l = mid; + else r = mid - 1; + } + if (nums.get(r) + nums.get(i) < target) ans += r + 1; + } + return ans; + } +} +``` +C++ 代码: +```C++ +class Solution { +public: + int countPairs(vector& nums, int target) { + sort(nums.begin(), nums.end()); + int n = nums.size(), ans = 0; + for (int i = 1; i < n; i++) { + int l = 0, r = i - 1; + while (l < r) { + int mid = l + r + 1 >> 1; + if (nums[mid] + nums[i] < target) l = mid; + else r = mid - 1; + } + if (nums[r] + nums[i] < target) ans += r + 1; + } + return ans; + } +}; + +``` +Python 代码: +```Python +class Solution: + def countPairs(self, nums: List[int], target: int) -> int: + nums.sort() + n, ans = len(nums), 0 + for i in range(1, n): + l, r = 0, i - 1 + while l < r: + mid = l + r + 1 >> 1 + if nums[mid] + nums[i] < target: l = mid + else: r = mid - 1 + if nums[r] + nums[i] < target: ans += r + 1 + return ans +``` +TypeScript 代码: +```TypeScript +function countPairs(nums: number[], target: number): number { + nums.sort((a,b)=>a-b); + let n = nums.length, ans = 0; + for (let i = 1; i < n; i++) { + let l = 0, r = i - 1; + while (l < r) { + const mid = l + r + 1 >> 1; + if (nums[mid] + nums[i] < target) l = mid; + else r = mid - 1; + } + if (nums[r] + nums[i] < target) ans += r + 1; + } + return ans; +}; +``` +* 时间复杂度:排序复杂度为 $O(n\log{n})$;构造答案复杂度为 $O(n\log{n})$。整体复杂度为 $O(n\log{n})$ +* 空间复杂度:$O(\log{n})$ + +--- + +### 排序 + 双指针 + +这是一种「遍历左端点,在左端点右侧找最大合法右端点」做法。 + +使用 `l` 和 `r` 分别指向排序好的 `nums` 的首尾。 + +若当前 $nums[l] + nums[r] \geq target$,说明此时对于 `l` 来说,`r` 并不合法,对 `r` 自减(左移)。 + +直到满足 $nums[l] + nums[r] < target$,此时对于 `l` 来说,找到了最右侧的合法右端点 `r`,在 $[l + 1, r]$ 期间的数必然仍满足 $nums[l] + nums[r] < target$,共有 $r - l$ 个(范围为 $[l + 1, r]$ )个合法右端点,需要被统计。 + +Java 代码: +```Java +class Solution { + public int countPairs(List nums, int target) { + Collections.sort(nums); + int n = nums.size(), ans = 0; + for (int l = 0, r = n - 1; l < r; l++) { + while (r >= 0 && nums.get(l) + nums.get(r) >= target) r--; + if (l < r) ans += r - l; + } + return ans; + } +} +``` +C++ 代码: +```C++ +class Solution { +public: + int countPairs(vector& nums, int target) { + sort(nums.begin(), nums.end()); + int n = nums.size(), ans = 0; + for (int l = 0, r = n - 1; l < r; l++) { + while (r >= 0 && nums[l] + nums[r] >= target) r--; + if (l < r) ans += r - l; + } + return ans; + } +}; +``` +Python 代码: +```Python +class Solution: + def countPairs(self, nums: List[int], target: int) -> int: + nums.sort() + n, ans = len(nums), 0 + l, r = 0, n - 1 + while l < r: + while r >= 0 and nums[l] + nums[r] >= target: r -= 1 + if l < r: ans += r - l + l += 1 + return ans +``` +TypeScript 代码: +```TypeScript +function countPairs(nums: number[], target: number): number { + nums.sort((a,b)=>a-b); + let n = nums.length, ans = 0; + for (let l = 0, r = n - 1; l < r; l++) { + while (r >= 0 && nums[l] + nums[r] >= target) r--; + if (l < r) ans += r - l; + } + return ans; +}; +``` +* 时间复杂度:排序复杂度为 $O(n\log{n})$;构造答案复杂度为 $O(n)$。整体复杂度为 $O(n\log{n})$ +* 空间复杂度:$O(\log{n})$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.2824` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 + diff --git "a/LeetCode/901-910/907. \345\255\220\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\345\200\274\344\271\213\345\222\214\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/901-910/907. \345\255\220\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\345\200\274\344\271\213\345\222\214\357\274\210\344\270\255\347\255\211\357\274\211.md" index cf7556ac..16b227e8 100644 --- "a/LeetCode/901-910/907. \345\255\220\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\345\200\274\344\271\213\345\222\214\357\274\210\344\270\255\347\255\211\357\274\211.md" +++ "b/LeetCode/901-910/907. \345\255\220\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\345\200\274\344\271\213\345\222\214\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -35,8 +35,6 @@ Tag : 「数学」、「单调栈」 ### 单调栈 + 数学 -> 原题解链接在 [这里](https://leetcode.cn/problems/sum-of-subarray-minimums/solution/by-ac_oier-h9cd/),本次增加了更为详细的细节说明。 - 原问题为求所有子数组的最小值之和。 统计所有子数组需要枚举左右端点,复杂度为 $O(n^2)$,对于每个子数组,我们还需要通过线性扫描的方式找到其最小值,复杂度为 $O(n)$,因此朴素解法的整体复杂度为 $O(n^3)$,题目给定数据范围为 $3 \times 10^4$,会 `TLE`。 @@ -100,6 +98,38 @@ class Solution { } } ``` +C++ 代码: +```C++ +class Solution { +public: + int MOD = 1e9 + 7; + int sumSubarrayMins(vector& arr) { + int n = arr.size(), ans = 0; + vector l(n, -1), r(n, n); + stack d; + for (int i = 0; i < n; i++) { + while (!d.empty() && arr[d.top()] >= arr[i]) { + r[d.top()] = i; + d.pop(); + } + d.push(i); + } + while (!d.empty()) d.pop(); + for (int i = n - 1; i >= 0; i--) { + while (!d.empty() && arr[d.top()] > arr[i]) { + l[d.top()] = i; + d.pop(); + } + d.push(i); + } + for (int i = 0; i < n; i++) { + long long a = i - l[i], b = r[i] - i; + ans = (ans + a * b % MOD * arr[i] % MOD) % MOD; + } + return ans; + } +}; +``` TypeScript 代码: ```TypeScript const MOD = 1000000007 @@ -177,6 +207,29 @@ class Solution { } } ``` +C++ 代码: +```C++ +class Solution { +public: + int MOD = 1e9 + 7; + int sumSubarrayMins(vector& arr) { + int n = arr.size(), ans = 0; + deque d; + for (int r = 0; r <= n; r++) { + int t = (r < n) ? arr[r] : 0; + while (!d.empty() && arr[d.back()] >= t) { + int cur = d.back(); + d.pop_back(); + int l = d.empty() ? -1 : d.back(); + long long a = cur - l, b = r - cur; + ans = (ans + a * b % MOD * arr[cur] % MOD) % MOD; + } + d.push_back(r); + } + return ans; + } +}; +``` TypeScript 代码: ```TypeScript const MOD = 1000000007