Array-LeetCode

怎么删除数组最后一个元素?
最后一个元素没有后面的值来覆盖,一般都是直接让数组长度减小1,让最后一个元素不可访问。

1.Two sum
2个for循环,O(N^2)

11.Container With Most Water
暴力解的话就是2个for循环,但是会 TLE...,O(N^2)过不了。
有个更好的线性时间复杂度O(N)的解法:就是双指针。
定义左右两个指针,因为是要求面积,如果面积要尽可能地大的话,那左右两个指针就是分别位于x轴的两端。
然后左或右指针代表的height太小的话,就移动到下个位置,并保存下当前的最大面积,之后每移动一次就更新一次最大面积直到找到位置。
这种方法就避免了多次对整个数组进行遍历。
细节:两个指针是怎么移动的,只要有一个指针比另一个指针小,就移动小的那个,相等的话,任意移动哪一个都可以。

167.Two Sum II - Input array is sorted
暴力2层for循环可以解,但是 TLE ,所以还是用双指针。

15.3Sum
这个问题的关键点在于:
1.这个数组需要排序
2.怎么避免重复的三个一组出现
避免出现重复的第一个数

思路:
在确定了第一个值之后,剩下的其实就是Two Sum II 了,用双指针或者hash map都可以

注意:
有个很坑的点是

//我最开始是这么写的
if(nums[i] == nums[i-1] && i!=0) {
                continue;
            }

那就会报错说vector出现未定义的行为因为访问到0-1的位置了,所以应该改成:
 if(i!=0 && nums[i] == nums[i-1] ) {
                continue;
            }

//顺便贴下AC的代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> arr;
        if(nums.size() < 3) {
            return arr;
        }
        sort(nums.begin(),nums.end());
        
        for(int i = 0; i < nums.size() - 2; i++) {
            if(nums[i] > 0) {
                break;
            }
            if(i!=0 && nums[i] == nums[i-1] ) {
                continue;
            }
            int left = i + 1;
            int right = nums.size() - 1;
           
            while(left < right) {
                int threeSum = nums[i] + nums[left] + nums[right];
                if(threeSum < 0) {
                    left++;
                } else if (threeSum > 0) {
                    right--;
                } else {
                    arr.push_back(vector<int>{nums[i],nums[left],nums[right]});
                    left++;
                    right--;
                    //清理掉重复的元素
                    while(left < right && nums[left] == nums[left-1] ) {
                        left++;
                        
                    }
                    while(left < right && nums[right] == nums[right + 1]) {
                        right--;
                    }
                }
            }
        }
        return arr;
    }
};
  1. Maximum Subarray
    思路:
    需要两个变量一个curSum来记录当前子序列和的值。如果下一个元素的值大于当前子序列加上下一元素值的和就舍弃掉这个前缀,
    而替换成下一个元素。如果相等的话,那保留前缀和替换成下一元素都可以。还需要一个globalSum来记录找到的最大子序列和。只要没有超过globalSum的就不更新这个值。
//贴上AC代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int curSum,globalSum;
        curSum = nums[0];
        globalSum = curSum;
        for(int i = 1; i < nums.size(); i++) {
            curSum = curSum + nums[i];
            if(curSum <= nums[i]) {
                curSum = nums[i];
            }
            if(curSum > globalSum) {
                globalSum = curSum;
            }         
        }
        return globalSum;
    }
};

题目说还可以用分治实现

//TODO
  1. Remove Element
    暴力解:
  2. 如果要删除数组的最后一个值,怎么删除,后面没有元素可以覆盖它了。
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        
        for(int i = 0; i < size; i++) {
            if(nums[i] == val) {
                for(int j = i + 1; j < size; j++) {
                    nums[j - 1] = nums[j]; 
                }
                //因为移除了一个元素
                i--;
                size--;
            }
        }
        return size;        
    }
}; 

//更简单的
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        if(nums.size() == 0) {
            return 0;
        }
        int size = 0;
        for(int i = 0; i < nums.size(); i++) {
            if(nums[i] != val) {
                nums[size] = nums[i];
                size++;
            }
        }
        return size; 
    }
}; 

除了暴力解,更好的办法就是用双指针。

//定义两个指针


posted @ 2020-12-24 21:18  Lylee  阅读(59)  评论(0)    收藏  举报