LeetCode刷题1-数组-简单难度

前言

为了准备考研复试以及提高自己的代码能力,我准备到复试之前尽量多刷些算法题目,主要以简单中等为主。每刷完一个标签的一个难度的题目就写博客汇总一下,目的主要是为了强迫自己去复习,提高熟练度。

LeetCode 1 两数之和

题目链接

题目大意

给定一个整数数组 nums 和一个整数目标值 target ,在数组中找出和为 target 的那两个整数,并返回它们的数组下标。
注意:每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

思路

由于给出的示例不保证数组有序,因此不应该优先考虑二分法,二分的话首先需要对数组进行排序,至少 O(NlogN)
这里可以考虑使用哈希表,以 {nums[i],i} 的形式存储。可以使用两遍循环,第一遍建立好哈希表,第二遍针对数组中的每个数,寻找在哈希表中是否有与其匹配的数。或者优化的方法是,只使用一次遍历,先判断已经建立的哈希表中是否有符合题意的数,如果没有,就将当前遍历到的数字存入表中。

时间复杂度:O(N),一次遍历即可
空间复杂度:O(N),主要是哈希表的开销

代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> m;
        for(int i=0;i<nums.size();i++){
            if(m.find(target-nums[i])!=m.end()){
                return {m[target-nums[i]],i};  
                //当前找到的匹配的数字的下标一定在前面
            }
            m[nums[i]]=i;
        }
        return {};
    }
};

LeetCode 26 删除排序数组中的重复项

题目链接

题目大意

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
不需要考虑数组中超出新长度后面的元素。

思路

这里比较关键的是理解不需要考虑数组中超出新长度后面的元素这个提示。那么我们可以直接对数组进行一次遍历,把每一个不重复的数字移到前面。可以设定一组双指针指针i指向当前最后一个不重复的数字放置的位置,指针j指向原数组中下一个需要判断是否重复的数字。将两个指针所指数字比较,如果不同,则将指针j所指数字放到指针i所指位置的下一个。由于指针i为数组下标,所以最终返回时还需加1,才是不重复数字的个数。如果原始数组为空,则直接返回0。

时间复杂度:O(N),一次遍历即可
空间复杂度:O(1)

代码

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int n=0;
        for(int i=1;i<nums.size();i++){
            if(nums[i]!=nums[n]){
                nums[++n]=nums[i];
            } 
        }
        return nums.size()==0?0:++n;
    }
};

LeetCode 27 移除元素

题目链接

题目大意

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

思路

由于小于数组新长度的数字可以为任意顺序,那么在一次遍历中,我们可以将所有需要移除的数字和数组末端的数字进行交换。利用双指针i和j指针i指向当前需要与val进行比较的数字,指针j指向数组末端可以用于交换的数字,如果指针i指的数字为val,则进行交换。注意,交换过后,i不能自增,还需要将交换过来的数字再和val比较,因为数组后端也可能有和val值相同的数字。

时间复杂度:O(N),一次遍历即可
空间复杂度:O(1)

代码

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int j=nums.size()-1;
        int i=0;
        while(i<=j)
            if(nums[i]==val){
                nums[i]=nums[j--];
            }
            else{
                i++;
            }
        return ++j;

    }
};

LeetCode 35 搜索插入位置

题目链接

题目大意

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

思路

当看到有序数组时,不要再想着O(N)的遍历方法了,优先考虑二分法。需要注意,本题还可能找不到目标值,因此,要找到大于等于目标值的最大值的位置,即为插入位置。

时间复杂度:O(NlogN)
空间复杂度:O(1)

代码

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int low=0,high=nums.size()-1;
        while(low<=high){
            int mid=(low+high)/2;
            if(target>nums[mid]) low=mid+1;
            else  high=mid-1;
        }
        return low;
    }
};

LeetCode 53 最大子序和

题目链接

题目大意

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

思路

这种题如果没有遇到过确实会一脸懵逼,不过做的多了也就没那么难了。简单的动态规划题目。对于数组中的每个位置i,我们都可以找到以这个位置为结尾的子数组的最大值max_sum[i],而整道题目的最大值也就是所有这些最大值中的最大值,即max(max_sum[i],i=0,1,2…)。而位置i为结尾的子数组的最大值为max(nums[i],nums[i]+max_sum[i-1]),这就是本题的DP转移方程

时间复杂度:O(N)
空间复杂度:O(1)

代码

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int maxValue=nums[0];
        for(int i=1;i<nums.size();i++){
            nums[i]=max(nums[i-1]+nums[i],nums[i]);
            maxValue=max(maxValue,nums[i]);
        }
        return maxValue;
    }
};

本题还有O(NlogN)的方法,即类似线段树的递归方法,官方题解也已给出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值