本刷题策略为leetcode官方的新手村策略,跟着主页官方的新手村策略刷题,按照每天刷三简单题或两中等题或一难题的速度刷题,每天预计花费1.5h
下面的顺序是探索卡中的顺序
数组
分为三部分
1.做好初始定义 2.运用基础算法思想 3.双索引技巧-对撞指针 4.双索引技巧-滑动窗口
1.做好初始定义
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
解法
难点就是不复制原数组要原地修改,解法为设置一个res,记录前面的0的个数,每次插入时只要插入到nums[i - res]中即可
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
解法
和移动零一样,只不过换成了判断是否等于val
给你一个 升序排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
解法
利用双指针,j用来存储应该插入的下标,i用来遍历
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
解法
int slow = 2, fast = 2;
while(fast < n)
{
if(nums[slow - 2] != nums[fast]) nums[slow ++] = nums[fast];
fast ++;
}
2.运用基础算法思想
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
必须在不使用库的sort函数的情况下解决这个问题。且仅使用常数空间
解法
指针p0,指向0应该插入的末尾,指针p1指向1应该插入的末尾。剩下的都是2,但是需要注意的是,在插入0的时候,1的指针要做相应的改变
for(int i = 0; i < n; i ++)
{
if(nums[i] == 1) swap(nums[i], nums[p1 ++]);
else if(nums[i] == 0)
{
swap(nums[i], nums[p0]);
if(p0 < p1)//如果p0小于p1,则此时nums[i] = 1 nums[p0] = 0,
//因为1的区间为p0 到p1,此时1区间的一个开头被吃掉了,要补上去
{
swap(nums[p1], nums[i]);
}
p0 ++, p1 ++;
}
}
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
解法
利用快速排序的变种求,模板题
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
解法
难点在于利用常数个存储空间,我们采用从尾开始遍历的方式,插入到nums1的尾部,此时不存在冲突问题。
3.双索引技巧-对撞指针
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
解法
双指针,一个指向头,一个指向尾,往中间遍历。这题居然是中等题。。。。。。
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
解法
难点就是要先移除所有的非字母数字
这里使用了isalnum()函数,判断是否为数字或字符,tolower()函数把字符串转换成小写,存储在sgood中
if(isalnum(ch)) sgood += tolower(ch);
给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。
元音字母包括 'a'、'e'、'i'、'o'、'u',且可能以大小写两种形式出现。
解法
难点是存储元音字母进行判断,之前采用了set方式但是很不方便,还是字符串最快
string yuan = "aeiouAEIOU";
bool isVolwer(char a, string yuan)//判断是否是元音
{
int n = yuan.size();
for(int i = 0; i < n; i ++)
if(a == yuan[i]) return true;
return false;
}
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
解法
左右指针,移动较短的那一边
双索引技巧-滑动窗口
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
解法
滑动窗口模板题
while(end < n)
{
sum += nums[end ++];
while(sum >= target)
{
res = min(res, end - start);
sum -= nums[start];
start ++;
}
}