双指针
977. 有序数组的平方
https://leetcode.cn/problems/squares-of-a-sorted-array/comments/
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
暴力排序法
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i = 0; i < nums.size(); i++){
nums[i] = nums[i] * nums[i];
}
sort(nums.begin(), nums.end());
return nums;
}
};双指针法
class Solution {
public:
vector<int> sortedSquares(vector<int> &nums) {
vector<int> result(nums.size(), 0);
int k = nums.size() - 1;
for (int i = 0, j = k; i < nums.size(), j >= i;) {
if (nums[j] * nums[j] > nums[i] * nums[i]) {
result[k--] = nums[j] * nums[j];
j--;
} else {
result[k--] = nums[i] * nums[i];
i++;
}
}
return result;
}
};数组其实是有序的, 只不过负数平方之后可能成为最大数了。那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。此时可以考虑双指针法了,i 指向起始位置,j 指向终止位置。定义一个新数组 result,和 nums 数组一样的大小,让 k 指向 result 数组终止位置。
189. 轮转数组
https://leetcode.cn/problems/rotate-array/
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
暴力轮转
双指针原地算法
先全部翻转一遍,再翻转前一段,最后翻转后一段。
88. 合并两个有序数组
https://leetcode.cn/problems/merge-sorted-array/
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
因为我们要放在 nums1 里面,所以我们从后往前遍历,从最大的开始比较,一个一个放进去,最后 nums2 还有剩就全部扔进去,nums1 还有剩说明已经全部放在了正确的位置,不用管。
283. 移动零
https://leetcode.cn/problems/move-zeroes
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
i 来遍历整个数组,遇到不是 0 的就交给 j 进行填充,最后再补 0。
167. 两数之和 II - 输入有序数组
https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
i 在最小,j 在最大,如果大了 j 就减一,如果小了 i 就加一。这样做可以减少很多不必要情况的判断。
344. 反转字符串
https://leetcode.cn/problems/reverse-string
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
无脑题,甚至直接 reverse 也能过。
557. 反转字符串中的单词 III
https://leetcode.cn/problems/reverse-words-in-a-string-iii
给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
遇到空格就反转之前的,最后再反转一下最后一个单词即可。reverse 可以用双指针实现。
876. 链表的中间结点
https://leetcode.cn/problems/middle-of-the-linked-list
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
普通双指针
遍历第一遍求长度,第二遍走到 n / 2 即可。
快慢指针
奇数情况是 q 到最后一个就不行了,偶数情况是到最后一个的下一个,也就是空。
3. 无重复字符的最长子串
https://leetcode.cn/problems/longest-substring-without-repeating-characters/
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
用一个哈希表来维护,当有重复字符的时候,j 指针就往右移,直到没有重复字符,最后取 max 即可。
567. 字符串的排列
https://leetcode.cn/problems/permutation-in-string/
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
换句话说,s1 的排列之一是 s2 的 子串 。
用两个哈希表进行维护,最后比较两个哈希表相同的“柱子数”是否为 h1 的总长度即可。
套模板即可,当窗口长度为 s1 的长度且有效位数符合时就可以返回 true。
27. 移除元素
https://leetcode.cn/problems/remove-element/
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
暴力
遇到需要删除的就将后面的元素一起往前移一格即可。因为少了一个,所以 i 也需要往前一格。
快慢指针
当快指针遇到需要删除的元素,慢指针不动,直到快指针指向不需要删除的数字,然后让快指针把不需删除的一个一个覆盖过去。
26. 删除有序数组中的重复项
https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组 nums 的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
一个指在前面一个指在后面,经典双指针问题。注意特判 i = 0 的情况。
更好的快慢指针做法,更加直观。
844. 比较含退格的字符串
https://leetcode.cn/problems/backspace-string-compare/
给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
注意使用 resize() 将后面无用的字符给去掉。
209. 长度最小的子数组
https://leetcode.cn/problems/minimum-size-subarray-sum/
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
经典滑动窗口问题,注意判断 res 没有被更新的情况。
904. 水果成篮
https://leetcode.cn/problems/fruit-into-baskets/
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。 给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
用哈希表,并且用一个变量来保存哈希表中有几个不同的水果种类,每次这个种类清空了或者存在了都会对 s 有所改变。
76. 最小覆盖子串
https://leetcode.cn/problems/minimum-window-substring/
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
用两个哈希表和一个 cnt 进行维护,经典滑动窗口。
更好的做法,可作为滑动窗口模板。
202. 快乐数
https://leetcode.cn/problems/happy-number/
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。 如果这个过程 结果为 1,那么这个数就是快乐数。 如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
用一个快慢指针,因为他会有循环,所以判断循环的数字是否为 1 就行。
15. 三数之和
https://leetcode.cn/problems/3sum/
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
首先需要把 i 给定下来,然后遍历 j 与 k 即可,需要注意的是我们需要进行去重,不然会有重复答案的出现。
18. 四数之和
https://leetcode.cn/problems/4sum/
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n a、b、c 和 d 互不相同 nums[a] + nums[b] + nums[c] + nums[d] == target 你可以按 任意顺序 返回答案 。
与三数之和区别不大,就是加一层循环就行了。
151. 反转字符串中的单词
https://leetcode.cn/problems/reverse-words-in-a-string/
给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s 中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
将每一个单词都放到前面,一个指针指向原本的字符串,另外一个指向最后成为结果的字符串。注意找到一个单词就要将其翻转。
5. 最长回文子串
https://leetcode.cn/problems/longest-palindromic-substring/
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
这道题难点在于需要从中间向外来走,还要考虑是奇数还是偶数的情况,注意 substr 时的边界问题。
438. 找到字符串中所有字母异位词
https://leetcode.cn/problems/find-all-anagrams-in-a-string/
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
按照模板写即可,值得一提的是这里处理缩小的时候和模板有所不同,根据题型自行适配。
912. 排序数组
https://leetcode.cn/problems/sort-an-array/
给你一个整数数组 nums,请你将该数组升序排列。
用归并排序解决。
快排。
493. 翻转对
https://leetcode.cn/problems/reverse-pairs/
给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。
你需要返回给定数组中的重要翻转对的数量。
归并排序加几行代码即可。
215. 数组中的第 K 个最大元素
https://leetcode.cn/problems/kth-largest-element-in-an-array/
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
42. 接雨水
https://leetcode.cn/problems/trapping-rain-water/
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
31. 下一个排列
https://leetcode.cn/problems/longest-common-subsequence/
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。 给你一个整数数组 nums ,找出 nums 的下一个排列。
必须 原地 修改,只允许使用额外常数空间。
165. 比较版本号
https://leetcode.cn/problems/compare-version-numbers/
给你两个版本号 version1 和 version2 ,请你比较它们。
版本号由一个或多个修订号组成,各修订号由一个 '.' 连接。每个修订号由 多位数字 组成,可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号,下标从 0 开始,最左边的修订号下标为 0 ,下一个修订号下标为 1 ,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。
比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较 忽略任何前导零后的整数值 。也就是说,修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号,则该修订号视为 0 。例如,版本 1.0 小于版本 1.1 ,因为它们下标为 0 的修订号相同,而下标为 1 的修订号分别为 0 和 1 ,0 < 1 。
返回规则如下:
如果 version1 > version2 返回 1, 如果 version1 < version2 返回 -1, 除此之外返回 0。
43. 字符串相乘
https://leetcode.cn/problems/multiply-strings/
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
240. 搜索二维矩阵 II
https://leetcode.cn/problems/search-a-2d-matrix-ii/
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。 每列的元素从上到下升序排列。
209. 长度最小的子数组
https://leetcode.cn/problems/minimum-size-subarray-sum/
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
11. 盛最多水的容器
https://leetcode.cn/problems/container-with-most-water/
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
最后更新于