leetcode题解-初级算法数组篇(1-5题)

7月保研的夏令营已经告一段落了,面试中被问了很多算法的问题,感觉自己算法知识有些许薄弱(acm大神忽略),所以准备开始刷leetcode,顺便也为面试准备,因为想把刷leet里面的一些心得给记下来,便于之后复习,所以在这里开博。之后会按里面的篇章顺序进行更新,喜欢的可以给文章点一个赞,如果文章有任何问题或者有更好的解法可以在评论中给出,下面开始题解,本篇章为初级算法的数组篇(1-5题):

第一题:从排序数组中删除重复项

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

算法说明:这题是简单题,题目中要求要用O(1)的空间复杂度,所以是不能额外建一个数组了,我的思路是建一个temp等于第一个数,再建一个res变量用于存储不同的元素个数,因为数组是排序的,所以对数组进行扫描,若扫描的值和temp不一样,则更新temp并且res++,把不一样的元素移到对应的位置num[res-1]。
其代码如下:

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

            }
        }
        return res;
    }
};

第二题:买卖股票的最佳时机 II

题目说明:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

算法:本题就是一题贪心,当后一天的价格比之前高就卖出,具体为什么可以自己仔细想一想。

代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int sum=0;
        if(prices.size()==1||prices.size()==0){
        return 0;
        }
        for(int i=0;i<prices.size()-1;i++){
        if(prices[i+1]>prices[i]){
            sum=sum+prices[i+1]-prices[i];        }
        }
        return sum;
    }
};

第三题:旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的原地算法。
该题的解法有很多,这里给出三种空间为O(1)的方法。
方法一:写一个旋转一次的函数,然后根据题目要求的k,旋转k次,这样空间复杂度为O(1),时间复杂度为O(N^K)。
方法二:和上个方法类似,不过移动的时候直接通过nums[i]与nums[(i+k)%nums.size()]这样对应,从而减少操作次数。空间复杂度O(1),时间复杂度O(N)。
方法三:这是另一个比较好的方法,建立一个变量times=k%n。然后对于一个数组从times开始把整个数组分为两个部分。如[1,2,3,4,5,6,7] 和 k = 3,此时n=7。times=3。则把[1,2,3,4,5,6,7]分成两个部分[1,2,3,4 | 5,6,7],然后把第一个部分翻转[4,3,2,1 | 7,6,5],把第二部分也翻转[4,3,2,1 | 7,6,5],最后把整个数组翻转得到最终答案[5,6,7,1,2,3,4],该方法时间复杂度O(n)。
该方法的代码如下:

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n=nums.size();
        int times=k%n;
        if(times==0)
            return;
        rotCore(nums,0,n-1-times);
        rotCore(nums,n-times,n-1);
        rotCore(nums,0,n-1);
    }
    void rotCore(vector<int>& nums,int b,int e){
        while(b<e){
            swap(nums[b],nums[e]);
            ++b;
            --e;
        }
        return;
    }
};

第四题 存在重复

题目描述:给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
算法说明:这题和第一题的不同之处在于不是有序的数组。方法1通过对每个元素判断是否有重复,时间复杂度O(n^2)。所以这里我采用了set容器,扫描的过程中把元素加入,如果有重复就返回true,因为set容器中的查找为红黑树,所以该方法的时间复杂度为O(nlogn)。代码如下:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        set<int> table;
        int i;
        for(i=0;i<nums.size();i++)    {
        if(table.count(nums[i])==1) return true;
         table.insert(nums[i]);
        }

        return false;

    }
};

第五题 只出现一次的数字

题目说明:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

算法说明:这道题目是面试中的原题了,有同学面试被问到过,难度在于线性时间复杂度和不使用额外空间,要满足这两个条件的本题的方法是使用异或。
首先我们知道异或对与一样的两个数他们的结果会是0,而且异或符合交换律,所以把数组中所有的数异或一遍就得到了结果,而且符合了线性复杂度和0额外空间,其代码如下:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int m=0;
        for(int i=0;i<nums.size();i++)
            m=m^nums[i];
        return m;
    }
};

6-11题的题解马上也会更新

猜你喜欢

转载自blog.csdn.net/zsx983786386/article/details/81663547
今日推荐