【一、Leetcode数组专题(1)easy】

【数组专题】

难度:easy



【第一题】 Two Sum(NO.1)

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:
Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

.

知识点: vector unordered_map

暴力解法

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

时间复杂度O(N^2) Runningtime: 112ms

网上的优化是hash table解法 时间复杂度O(n)

学习了一下hash table ,解法如下

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int i;
        vector<int> re;
        unordered_map<int,int> mapping;
        int gap=0;

        for(i=0; i<nums.size(); i++)
            mapping[nums[i]]=i;

        for(i=0; i<nums.size(); i++){
            gap = target - nums[i];//注意这里,可以省去比较;
            if( mapping.find(gap) != mapping.end() && mapping[gap]!=i){ // 多了一个判定条件,即找到的值不能为nums[i]本身  即3+3=6的情况
                re.push_back(i);
                re.push_back(mapping[gap]);
                return re;
            }
        }
    }
};

时间复杂度 O(n) Runningtime: 9ms
效率大大提高了

iterator find(const key_type&k);
const_iterator find(const key_type&k)const;

mapping.find(gap) 返回为迭代器
获取迭代器到元素
搜索容器中的一个元素,其中k为关键字,如果发现,返回一个迭代器到它,否则它返回一个迭代器到unordered_map :: end(元素超过容器的结尾)。
一个学习哈希表的网址,看完后发现自己以前其实学习过哈希表的,真是忘的一干二净了。。
http://www.cnblogs.com/dolphin0520/archive/2012/09/28/2700000.html
mapping.find(gap) != mapping.end()说明存在gap值,如果==mapping.end()说明不存在

.

gap = target - nums[i];//注意这里,可以省去比较;减少一定复杂度
与gap+nums[i]=target的不同,仔细体会

.

哈希表 使用条件:key是不可以重复的,但是value可以重复

大神级解法,看看得了,与9ms思想相差不大,少一个for循环;不看此解法也行。
Running time 3ms

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> res;
        unordered_map<int,int> hm;
        for(int i = 0; i != nums.size();i++){
            int temp = target - nums[i];
            if(hm.find(temp) != hm.end())
            {
                res.push_back(hm[temp]);
                res.push_back(i);
                  return res;
            }
             hm[nums[i]] = i;
        }
    }
};


第二题 Remove Duplicates from Sorted Array(NO.26)

题目描述

Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

For example,
Given input array nums = [1,1,2],

Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn’t matter what you leave beyond the new length.

vector慎用erase 和查找 代码很方便 但开销太大
比如下面这个,时间开销为O(n^3),无法提交。

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int len=nums.size();
        for(int i=0; i<nums.size(); i++){
            for(int j=i+1; j<nums.size(); j++){
                if(nums[i]==nums[j]){
                    nums.erase(nums.begin()+j);
                    j--;//删除后所有数组会往前移动 所j要减一个
                    len--;
                }
            }
        }
        return len; 
    }
};

卡点:erase删除开销太大,不能使用,那用什么来替代重复值的位置内容?
问题:审题不清楚,题目说了已经排好序的。这样难度降低了一层其实。

改进:i,j两个“指针”往前走的思想;覆盖前面数组内容

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size()==0) return 0;

        int i=0;
        for(int j=1; j<nums.size(); j++){
            if(nums[i]!=nums[j]){
                i++;
                nums[i]=nums[j];
            }
        }
        return i+1;

    }
};

时间复杂度O(n) Runningtime 26ms



第三题 Remove Element (NO.27)

题目描述

Given an array and a value, remove all instances of that value in place and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

The order of elements can be changed. It doesn’t matter what you leave beyond the new length.

Example:
Given input array nums = [3,2,2,3], val = 3

Your function should return length = 2, with the first two elements of nums being 2.

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {

        int i=0;
        for(i=0; i<nums.size(); i++){
            if(nums[i]==val){
                nums.erase(nums.begin()+i);
                i--;
            }
        }

        return nums.size();
    }
};

时间复杂度:近似是O(n),因为erase不一定是O(n)

runningtime:3ms

第二种解法,效率差不多,主要了解下remove用法(remove配合erase使用),记不住也没事;估计用不到;

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        auto it = remove(nums.begin(), nums.end(), val);
        nums.erase(it, nums.end());
        return nums.size();
    }
};

时间复杂度 O(2n)=O(n)
Runningtime 6ms

romve没有真的删除值,只是把统一val放到了begin和end中的最后几个位置,返回的是第一个val的开始位置
所以erase直接删除从 it到end,就是真正删除了所有val,详细查阅下自己的c++笔记。



第四题 Search Insert Position (NO.35)

题目描述

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.

[1,3,5,6], 5 → 2

[1,3,5,6], 2 → 1

[1,3,5,6], 7 → 4

[1,3,5,6], 0 → 0

非常明显的二分搜索方法;

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int low=0;
        int high=nums.size()-1;
        int mid;

        while(low<=high){
            mid=(low+high)/2;
            if (nums[mid]==target) return mid;
            else if (nums[mid]>target) high=mid-1;
            else low=low+1;
        }
        return low;

    }
};

时间复杂度O(n) Runningtime:9ms



第五题 Maximum Subarray(No.53)

问题描述

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [-2,1,-3,4,-1,2,1,-5,4],

the contiguous subarray [4,-1,2,1] has the largest sum = 6.

卡点:除了暴力列出所有组合,求出最大的一个和,想不到别的方法。。。无从下手
方案:好好学习学习。。。第一次接触;
两个值,一个值(sum)累加,并在加到小于0时清0;
另一个值(flag)记录并**更新**sum累加过程中的最大值。

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

时间复杂度O(n) Runningtime:13ms

这其实就是一种分治解法(动态规划),好好学习;



第六题 Plus One(No.66)

题目描述
Given a non-negative integer represented as a non-empty array of digits, plus one to the integer.

You may assume the integer do not contain any leading zero, except the number 0 itself.

The digits are stored such that the most significant digit is at the head of the list.

卡点:没思路。以前没有接触过。
思路:应该尝试以下解决方法,找到规律。
首先需要个循环遍历数组,
其次,整体上分为两种
1、若最后一位不是9(<9),则最后一位直接+1 return;

2、若最后一位是9(其他 else),则考虑进位。

class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {
        for(int i=digits.size()-1 ; i>=0; i--){
            if(digits[i]<9){
                digits[i]++;
                return digits;
            }    
            else{
                digits[i]=0;    
            }
        }
        digits[0]=1;
        digits.push_back(0);
        return digits;

    }
};

时间复杂度 O(n) RunningTime 3ms



第七题 Merge Sorted Array(No.88)

题目描述
Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.

总结:坑爹的描述,题目意思是数组为空,但m,n不一定为空!
所以长度要用m,n,不要用size。
错误解法

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int i=m-1;
        int j=n-1;

        if(m==0){
            nums1.assign(nums2.begin(),nums2.end());
            return;
        }

        while(i>=0&&j>=0){
            if(nums1[i]<=nums2[j]){
                nums1.insert(nums1.begin()+i+1,nums2[j]);
                j--;
            }
            else
                i--;
        }

        while(j>=0){
            nums1.insert(nums1.begin(),nums2[j]);
            j--;
        }
        return;

    }
};

错误原因,0的影响,m,n的影响,不能直接用size要用m,n,数组为空,但m,n不一定为空!比较蛋疼。

正确解法:
要从m+n-1 的位置开始,从后往前放置数字。

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int i=m-1;
        int j=n-1;
        int k = m+n-1;
        while(i >=0 && j>=0)
        {
            if(nums1[i] > nums2[j])
                nums1[k--] = nums1[i--];
            else
                nums1[k--] = nums2[j--];
        }
        while(j>=0)
            nums1[k--] = nums2[j--];
    }

};
时间复杂度O(n),Runningtime 3ms


第八题 Pascal’s Triangle(No.118)

题目描述
Given numRows, generate the first numRows of Pascal’s triangle.

For example, given numRows = 5,
Return

[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]

想法:每个元素等于上一行相邻两个元素的和
(每一层的第i个位置,等于上一层第i-1与第i个位置之和。)
实施
1、前两行特殊处理;
2、第三行开始施行 [i-1]、[i]相加;

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> result;
        if( numRows==0) return result;

        result.push_back(vector<int>(1,1));

        for(int i=2; i<=numRows; i++){
            vector<int> current(i,1);  //  i个1
            vector<int> &prev=result[i-2];  //上一行,因为数组从零开始,
            //数组第0行  对应三角形第一行 i=1;
            //数组第1行  对应三角形第二行 i=2;
            //数组第2行  对应三角形第三行 i=3 上   上一行为数组第一行  prev[(i=3)3-2=1];

            for(int j=1; j<i-1; j++){
                current[j]=prev[j]+prev[j-1];
            }

            result.push_back(current);
        }
        return result;

    }
};

时间复杂度 O(n^2) Runningtime 3ms



第九题 Pascal’s Triangle II(No.119)

题目描述
Given an index k, return the kth row of the Pascal’s triangle.

For example, given k = 3,
Return [1,3,3,1].

Note:
Could you optimize your algorithm to use only O(k) extra space?

可能会考,因为有一个考点就是能否省去额外空间,在面试中出现的可能性大一些,不过总体比较简单,电面中比较合适。

这道题跟Pascal’s Triangle很类似,只是这里只需要求出某一行的结果。Pascal’s Triangle中因为是求出全部结果,所以我们需要上一行的数据就很自然的可以去取。而这里我们只需要一行数据,就得考虑一下是不是能只用一行的空间来存储结果而不需要额外的来存储上一行呢?这里确实是可以实现的。

对于每一行我们知道如果从前往后扫,第i个元素的值等于上一行的res[i]+res[i+1],可以看到数据是往前看的,如果我们只用一行空间,那么需要的数据就会被覆盖掉。所以这里采取的方法是从后往前扫,这样每次需要的数据就是res[i]+res[i-1],我们需要的数据不会被覆盖,因为需要的res[i]只在当前步用,下一步就不需要了。这个技巧在动态规划省空间时也经常使用,主要就是看我们需要的数据是原来的数据还是新的数据来决定我们遍历的方向。时间复杂度还是O(n^2),而空间这里是O(k)来存储结果,仍然不需要额外空间。

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> A(rowIndex+1,0);    // 题目中的k是从0开始的  所以要+1; 初始全部赋值为0,因为下面有0+1=1的更新  //  rowIndex=4   [1,3,3,1,0] i=3

        A[0]=1;
        for(int i=1;i<rowIndex+1;i++){  // i是个数,所以从1开始
            for(int j=i; j>=1; j--){   //大于等于1 ,因为第一个就是1.不用更新
                A[j]=A[j]+A[j-1];
            }
        }
        return A;


    }
};

数组首先申请全部空间row+1;
每次实际利用空间 i;
每次增大一个空间到 i+1;
所以,从后向前,先确认 最后一个位置(i+1)值,再依次向前确认,
这题想法很好,回头再看看。
时间复杂度O(n^2) 空间复杂度O(k),Runningtime 0ms



第十题 Best Time to Buy and Sell Stock(NO.121)

题目描述
Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Example 1:
Input: [7, 1, 5, 3, 6, 4]
Output: 5
max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)

Example 2:
Input: [7, 6, 4, 3, 1]
Output: 0
In this case, no transaction is done, i.e. max profit = 0.

重点复习,这种标记min和max的贪心算法,本题我的首要想法还是暴力法。。。弄个两层循环。。。感觉自己还是太菜,没有想法。
贪心法,分别找到价格最低和最高的一天,低进高出,注意最低的一天要在最高的一天之前。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()<2) return 0;

        int max=0;
        int min=prices[0];//先假设第一个最小

        for(int i=0; i<prices.size(); i++)
        {
            if(prices[i]<min)    
                min=prices[i];
            if(prices[i]-min>max)
                max=prices[i]-min;
        }
        return max;


    }
};

时间复杂度O(n) 空间复杂度O(1)(只有两个变量的空间)
Runningtime 6ms;



第十一题 Best Time to Buy and Sell Stock II(No.122)

题目描述
Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

完全没有想法,感觉无从下手。
总不能把所有的组合情况都列出来吧?

5min后有点想法,只要后一个比前一个大,就卖出,如果下一个比当前卖出的大,则再买入当前,然后继续卖出后一个,如此反复。因为只要后面继续比前面的大,那么收益就是正的会累加,卖了再买就行。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()<2) return 0;

        int sum=0;
        int flag=0;

        for(int i=1;i<prices.size();i++)
        {
            if((flag=prices[i]-prices[i-1]) > 0)   
                sum=sum+flag;
        }
        return sum;   
    }
};

时间复杂度 O(n)
Runningtime:6ms

此想法是正确的。。。。好激动。。。。。第一次自己想出来和标答一样。。。。。干TMD。。。
感觉自己智商还是在线的。
总结:贪心法,低进高出,把所有正的价格差价相加起来。

我发现困得时候不要看机器学习视频,必睡着,做做算法反而提神。
注:以后所有for和if的括号都要换行!!!这样以博主智商看着清晰,方便理解。。。。从此加入换行党。。



第十二题 Two Sum II - Input array is sorted(No.167)

题目描述
Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution and you may not use the same element twice.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
本身这题不用刷了。。好奇点开发现简单顺手就写了。。
此题和第一题出差不多,改了一个判定条件,其他没变。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
         int i;
        vector<int> re;
        unordered_map<int,int> mapping;
        int gap=0;

        for(i=0; i<nums.size(); i++)
            mapping[nums[i]]=i;

        for(i=0; i<nums.size(); i++){
            gap = target - nums[i];//注意这里,可以省去比较;
            if( mapping.find(gap) != mapping.end() && mapping[gap]>i){ // 多了一个判定条件,即找到的值不能为nums[i]本身  即3+3=6的情况
                re.push_back(i+1);
                re.push_back(mapping[gap]+1);
                return re;
            }
        }
    }
};

时间复杂度O(n)
Runningtime 9ms



数组的Easy专题到此结束了啦!

跟博主一起进入下一个任务吧!(数组 medium专题)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值