天天看点

LeetCode刷题(一)-----数组-------easy部分

LeetCode刷题(一)-----数组-------easy部分

1.两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
           

数组长度:nums.length

nums.size() 获取向量元素个数;

题解:

方法一:暴力法—暴力枚举

暴力法很简单,遍历每个元素 xx,并查找是否存在一个值与 target - xtarget−x 相等的目标元素。

• 时间复杂度 O(n^2)

• 空间复杂度 O(1)

• 总结:该方法简单但是时间复杂度为O(n2),空间复杂度为O(1);运行速度慢且内存空间消耗大

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

           

方法二:两遍哈希表

为了对运行时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找出它的索引。保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。

通过以空间换取速度的方式,我们可以将查找时间从 O(n)降低到 O(1)。哈希表正是为此目的而构建的,它支持以 近似 恒定的时间进行快速查找。我用“近似”来描述,是因为一旦出现冲突,查找用时可能会退化到 O(n)。但只要你仔细地挑选哈希函数,在哈希表中进行查找的用时应当被摊销为 O(1)。

一个简单的实现使用了两次迭代。在第一次迭代中,我们将每个元素的值和它的索引添加到表中。然后,在第二次迭代中,我们将检查每个元素所对应的目标元素(target - nums[i])是否存在于表中。

注意,该目标元素不能是 nums[i]本身!

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int,int> a;//建立hash表存放数组元素
        vector<int> b(2,-1);//存放结果
        for(int i=0;i<nums.size();i++) //将数组元素插入哈希表中
            a.insert(map<int,int>::value_type(nums[i],i));
        for(int i=0;i<nums.size();i++)
        {
            if(a.count(target-nums[i])>0&&(a[target-nums[i]]!=i))
            //判断是否找到目标元素且目标元素不能是本身
            {
                b[0]=i;
                b[1]=a[target-nums[i]];
                break;
            }
        }
        return b;
    };
};

           

注:

1.该方法用map实现,map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力

方法三:一编哈希表

改进:在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。如果它存在,那我们已经找到了对应解,并立即将其返回。

事实证明,我们可以一次完成。在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。如果它存在,那我们已经找到了对应解,并立即将其返回。

LeetCode刷题(一)-----数组-------easy部分
26.删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
           

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

说明:为什么返回数值是整数,但输出的答案是数组呢?请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

方法:双指针法

算法

数组完成排序后,我们可以放置两个指针 i和 j,其中 i是慢指针,而 j 是快指针。只要 nums[i]不等于nums[j],我们就增加 jj以跳过重复项。

当我们遇到 nums[j]不等于nums[i]时,跳过重复项的运行已经结束,因此我们必须把它(nums[j])的值复制到 nums[i + 1]。然后递增 i,接着我们将再次重复相同的过程,直到 j到达数组的末尾为止。

LeetCode刷题(一)-----数组-------easy部分

复杂度分析

• 时间复杂度:O(n),假设数组的长度是n,那么i和j分别最多遍历n步。

• 空间复杂度:O(1)。

27.移除元素

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

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

我的解法:

LeetCode刷题(一)-----数组-------easy部分

思路

既然问题要求我们就地删除给定值的所有元素,我们就必须用 O(1)的额外空间来处理它。如何解决?我们可以保留两个指针i和j,其中i是慢指针,j是快指针。

算法

当 nums[j]与给定的值相等时,递增j以跳过该元素。只要nums[j]不等于val,我们就复制 nums[j]到 nums[i]并同时递增两个索引。重复这一过程,直到j到达数组的末尾,该数组的新长度为i。

该解法与 删除排序数组中的重复项 的解法十分相似。

35.搜索插入位置

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

你可以假设数组中无重复元素。

我的解法:
LeetCode刷题(一)-----数组-------easy部分
53.最大子序和

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

题解:思路

这道题用动态规划的思路并不难解决,比较难的是后文提出的用分治法求解,但由于其不是最优解法,所以先不列出来

动态规划的是首先对数组进行遍历,当前最大连续子序列和为 sum,结果为 ans。如果 sum > 0,则说明 sum 对结果有增益效果,则 sum 保留并加上当前遍历数字。如果 sum <= 0,则说明 sum 对结果无增益效果,需要舍弃,则 sum 直接更新为当前遍历数字。每次比较 sum 和 ans的大小,将最大值置为ans,遍历结束返回结果。

时间复杂度:O(n)

LeetCode刷题(一)-----数组-------easy部分

代码二

时间复杂度:O(n)

空间复杂度:O(n)

LeetCode刷题(一)-----数组-------easy部分

优化空间

因为以当前数结尾的最大序列和仅与前一个序列和相关,所以可以用一个变量保存。

LeetCode刷题(一)-----数组-------easy部分

我的:

LeetCode刷题(一)-----数组-------easy部分

想知道更多解法可以去leetcode上哈。欢迎点赞^-