本刷题策略为leetcode官方的新手村策略,跟着主页官方的新手村策略刷题,按照每天刷三简单题或两中等题或一难题的速度刷题,每天预计花费1.5h

下面的顺序是探索卡中的顺序

数组

分为三部分

1.做好初始定义 2.运用基础算法思想 3.双索引技巧-对撞指针 4.双索引技巧-滑动窗口

1.做好初始定义

移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

解法

难点就是不复制原数组要原地修改,解法为设置一个res,记录前面的0的个数,每次插入时只要插入到nums[i - res]中即可

移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

解法

和移动零一样,只不过换成了判断是否等于val

删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

解法

利用双指针,j用来存储应该插入的下标,i用来遍历

删除有序数组中的重复项II

给你一个有序数组 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 ++;
            }
        }

数组中第K个最大的数

给定整数数组 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.双索引技巧-对撞指针

两数之和 II - 输入有序数组

给你一个下标从 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 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

学习机器学习要刷要leetcode刷题 新手刷leetcode_c++

 解法

左右指针,移动较短的那一边

双索引技巧-滑动窗口

长度最小的子数组

给定一个含有 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 ++;
            }
        }