LeetCode数组解题模板

一、模板以及题目分类

1、头尾指针向中间逼近

int pos1 = 0;
int pos2 = nums.size() - 1;
while (pos1<pos2) {
    //判断条件

    //pos更改条件
    if (nums[pos1]<nums[pos2])
        pos1++;
    else
        pos2--;
}

经典的找和的问题都可以从这种思路下手,2数之和,3数之和,还注意要区分是寻找值还是索引(寻找索引则不能排序),是否允许有重复,不允许重复时要怎样避开重复值。

避开重复值的方法,当然,在3sum和4sum中的ij要稍微做修改

while(i<nums.size()-1 && nums[i] == nums[i+1]){
    i++;
}
i++;

 

11. Container With Most Water https://leetcode.com/problems/container-with-most-water/description/

int maxArea(vector<int>& height) {
    int max = 0;
    int pos1 = 0;
    int pos2 = height.size() - 1;
    while (pos1<pos2) {
        int temp = min(height[pos1], height[pos2])*(pos2 - pos1);
        if (temp>max) {
            max = temp;
        }
        if (height[pos1]<height[pos2])
            pos1++;
        else
            pos2--;
    }
    return max;
}
View Code

1、注意什么时候左指针加,什么时候右指针减 

 

15. 3Sum https://leetcode.com/problems/3sum/description/

sort(nums.begin(), nums.end());
vector<vector<int>> res;
for (unsigned int i = 0; i<nums.size(); i++) {
    if ((i>0) && (nums[i] == nums[i - 1]))
        continue;
    int l = i + 1, r = nums.size() - 1;
    while (l<r) {
        int s = nums[i] + nums[l] + nums[r];
        if (s>0) r--;
        else if (s<0) l++;
        else {
            res.push_back(vector<int> {nums[i], nums[l], nums[r]});
            while (l<r && nums[l] == nums[l + 1]) l++;
            l++;
        }
    }
}
return res;
View Code

1、在找到合适的组合之后需要一定一个索引值,不然循环就不能继续了

2、注意怎样去除重复值

 

16. 3Sum Closest https://leetcode.com/problems/3sum-closest/description/

1、再做一下熟悉一下

sort(nums.begin(),nums.end());
        int result = INT_MAX;
        int min = INT_MAX;
        for(size_t i=0;i<nums.size()-2;i++){
            int j = i+1;
            int k = nums.size()-1;
            while(j<k){
                int temp = nums[i]+nums[j]+nums[k];
                if(abs(temp-target)<min){
                    result = temp;
                    min = abs(temp-target);
                }
                if(temp < target){
                    j++;
                }else if(temp > target){
                    k--;
                }else if(temp == target){
                    return temp;
                }
            }
        }
        return result;
3 Sum Closet

 

18、4sum https://leetcode.com/problems/4sum/description/

vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> result;
        if(nums.size() < 4) return result;
        sort(nums.begin(),nums.end());
        for(size_t i = 0;i<nums.size()-3;){
            for(size_t j =i+1;j<nums.size()-2;){
                int k = j+1;
                int l = nums.size()-1;
                while(k<l){
                    if(nums[i]+nums[j]+nums[k]+nums[l] == target){
                        result.push_back(vector<int>{nums[i],nums[j],nums[k],nums[l]});
                        while(k<nums.size()-1 && nums[k] == nums[k+1])k++;k++;
                    }else if(nums[i]+nums[j]+nums[k]+nums[l] < target){
                        while(k<nums.size()-1 && nums[k] == nums[k+1])k++;k++;
                    }else{
                        while(l>1 && nums[l] == nums[l-1])l--;l--;
                    }
                }
                while(j<nums.size()-2 && nums[j] == nums[j+1])j++;j++;
            }
             while(i<nums.size()-3 && nums[i] == nums[i+1])i++;i++;
        }
        return result;
    }
four sum

 

2、数组内部移位

size_t pos1 = 0;//目的位置
//i为开始位置
for(size_t i =0;i<nums.size();i++){
    //条件
    if(nums[i] != val){
         //数组整体向前移
        nums[pos1++] = nums[i];
    }
}
return pos1;

需要维持一个开始位置,和一个目的位置,直接看例子

26. Remove Duplicates from Sorted Array https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/

int removeDuplicates(vector<int> nums) {
    if (nums.size() == 0) return 0;
    size_t pos = 1;
    for (size_t i = 1; i < nums.size(); i++) {
        if (nums[i - 1] != nums[i])
            nums[pos++] = nums[i];
    }
    return pos - 1;
}
LeetCode 26

1、如果前一个等于当前,代表当前值是重复,反之,如果不是则需要将当前值移位到pos处

2、边界条件,pos是从1开始,因为前一个存在的情况至少要从1开始

 

27. Remove Element https://leetcode.com/problems/remove-element/description/

同上一个方法

 

80. Remove Duplicates from Sorted Array II https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/description/

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size() == 0) return 0;
        int pos1 = 1;
        int repeat = 0;
        for(int i=1;i<nums.size();i++){
            if(nums[i] == nums[i-1] && repeat == 1){
                continue;
            }else if(nums[i] == nums[i-1] && repeat != 1){
                ++repeat;
            }else{
                repeat = 0;
            }
            nums[pos1++] = nums[i];
        }
        return pos1;
    }
};
View Code

 

 

3、排列问题

31. Next Permutation https://leetcode.com/problems/next-permutation/description/

    void nextPermutation(vector<int>& nums) {
        int n = nums.size(), k, l;
        for (k = n - 2; k >= 0; k--) {
            if (nums[k] < nums[k + 1]) {
                break;
            }
        }
        if (k < 0) {
            reverse(nums.begin(), nums.end());
        } else {
            for (l = n - 1; l > k; l--) {
                if (nums[l] > nums[k]) {
                    break;
                }
            } 
            swap(nums[k], nums[l]);
            reverse(nums.begin() + k + 1, nums.end());
        }
    }
View Code

1、注意怎么将代码写得简单,第一次遍历的时候,从size()-1到0遍历,在结尾处判断是否小于0,如果使用while循环将条件写在一起,则判断条件也会更加复杂

2、如果给定的排列是最大的,则需要返回最小排列

3、第二次寻找的时候从尾部开始寻找,这样可以减少代码复杂度,因为从头部开始寻找的时候需要额外判断所有值比目的值都大的情况。

 

4、二分查找

注意二分查找的区间是[first, last],还是[first, last),两种区间的处理方式是不一样的,while循环中是否有等于也有影响,没有等于时当nums.size()==0时不能进入循环

二分查找的标准例子:

int binarysearch(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1;
    while (left <= right) {
        int middle = (left + right) / 2;
        if (nums[middle] == target) {
            return middle;
        }
        else if (nums[middle] < target) {
            left = middle + 1;
        }
        else {
            right = middle - 1;
        }
    }return -1;
}

注意while循环在退出的时候left==right总是成立的

当数组中有重复元素的时候可以用二分查找来上下边界的情况

找上边界,尽量固定住右侧,即右侧发现相等元素时直接让right=middle,而不是middle-1,因为除2的情况下元素偏向左边,让左边加1就不会陷入死循环:

int left = 0;
int right = nums.size()-1;
while(left < right){
  int middle = (left + right)/2;
  if(nums[middle]<target)
    left = middle+1;
  else
    right = middle;
}

同理,寻找右边界的时候尽量固定住左边,让middle向右偏:

left = 0;
right = nums.size()-1;
while(left < right){
  int middle = (left + right)/2 + 1;
  if(nums[middle] > target)
    right = middle -1;
  else
    left = middle+1;
}
if(
right<num.size() && data[right] !=target) right--;

 但是此时退出状态有两种,pos2和pos1指向最后一个元素,或是pos2和pos1指向最后一个元素的下一个元素。所以再加上一个

if(pos2 <data.size() && data[pos2] != k) pos2 --;

 

33. Search in Rotated Sorted Array https://leetcode.com/problems/search-in-rotated-sorted-array/description/

    int search(vector<int>& nums, int target) {
        int pos1 = 0;
        int pos2 = nums.size()-1;
        while(pos1 <= pos2){
            int middle = (pos1+pos2)/2;
            if(nums[middle]== target){
                return middle;
            }else if(nums[middle]>=nums[pos1]){
                if(nums[middle] > target && nums[pos1] <= target){
                    pos2 = middle-1;
                }else{
                     pos1 = middle+1;
                }
            }else{
                if(nums[middle] < target && nums[pos2] >= target){
                    pos1 = middle+1;
                }else{
                    pos2 = middle-1;
                }
            }
        }
        return -1;
    }
View Code

 

 34. Find First and Last Position of Element in Sorted Array https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/description/

    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.size() ==0) return {-1,-1};
        int left = 0;
        int right = nums.size()-1;
        while(left < right){
            int middle = (left + right)/2;
            if(nums[middle]<target)
                left = middle+1;
            else
                right = middle;
        }
        vector<int> result(2,-1);
        if(nums[left] == target)
            result[0] = left;
        else
            return result;
        left = 0;
        right = nums.size()-1;
        while(left < right){
            int middle = (left + right)/2 + 1;
            if(nums[middle] > target)
                right = middle -1;
            else
                left = middle;
        }
        result[1] = left;
        return result;
    }
View Code

1、注意当数组长度为0的时候,找不到元素的时候这两种情况的边界条件

2、熟记二分查找寻找边界

 

81. Search in Rotated Sorted Array II https://leetcode.com/problems/search-in-rotated-sorted-array-ii/description/

1、最后一种情况的处理需要注意

 

153. Find Minimum in Rotated Sorted Array https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/description/

class Solution {
public:
    int findMin(vector<int>& nums) {
        int pos1 = 0;
        int pos2 = nums.size()-1;
        while(pos1<pos2){
            int middle = (pos1+pos2)/2;
            if(nums[pos1]<=nums[middle] && nums[middle]<nums[pos2]){
                return nums[pos1];
            }else if(nums[middle] < nums[pos2] && nums[pos2]<nums[pos1]){
                pos2 = middle;
            }else{
                pos1 = middle+1;
            }
        }
        return nums[pos1];
    }
};
View Code

 

209. Minimum Size Subarray Sum https://leetcode.com/problems/minimum-size-subarray-sum/description/

二分查找的思路,先使用一个单调递增的数列来存储开头到当前位置的长度和(数组项全为正数),每次使用二分法寻找第一个大于sum[i]+s的位置,也就是最小长度。代码写法可以好好的参考一下。

int n = nums.size();
    if (n == 0)
        return 0;
    int ans = INT_MAX;
    vector<int> sums(n + 1, 0); //size = n+1 for easier calculations
    //sums[0]=0 : Meaning that it is the sum of first 0 elements
    //sums[1]=A[0] : Sum of first 1 elements
    //ans so on...
    for (int i = 1; i <= n; i++)
        sums[i] = sums[i - 1] + nums[i - 1];
    for (int i = 1; i <= n; i++) {
        int to_find = s + sums[i - 1];
        auto bound = lower_bound(sums.begin(), sums.end(), to_find);
        if (bound != sums.end()) {
            ans = min(ans, static_cast<int>(bound - (sums.begin() + i - 1)));
        }
    }
    return (ans != INT_MAX) ? ans : 0;
View Code

维护一个值大于s的序列,向前加一个数的时候,再从尾部减去直到序列小于s,然后又向前读取数组直到大于s

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT_MAX;
        int pos = 0;
        int sum = 0;
        for(int i=0;i<nums.size();i++){
            sum = sum + nums[i];
            while(sum>=s){
                result = min(i-pos+1,result);
                sum = sum - nums[pos++];
            }
        }
        if(result == INT_MAX)
            return 0;
        return result;
    }
};
View Code

1、边界条件当数组所有元素和都小于s的时候需要特殊处理

 

5、遍历数组

有很多遍历数组的题是使用遍历过程中将数组中的值置为负数来存储数据

35. Search Insert Position https://leetcode.com/problems/search-insert-position/description/

    int searchInsert(vector<int>& nums, int target) {
        int pos = 0;
        for(size_t i = 0;i<nums.size();i++){
            if(nums[i]<target)
                pos++;
            else
                return pos;
        }
        return pos;
    }
View Code

 

219. Contains Duplicate II https://leetcode.com/problems/contains-duplicate-ii/description/

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        map<int,int> map;
        for(int i=0;i<nums.size();i++){
            if(map[nums[i]] != 0 && (i-map[nums[i]]+1)<=k)
                return true;
            else
                map[nums[i]] = i+1;
        }
        return false;
    }
};
View Code

 

238. Product of Array Except Self https://leetcode.com/problems/product-of-array-except-self/description/

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        long long mul = 1;
        int zero = 0;
        for(int i=0;i<nums.size();i++){
            if(nums[i] != 0){
                mul = mul*nums[i];
            }else{
                zero++;
            }
        }
        vector<int> result(nums.size(),0);
        if(zero >= 2)
            return result;
        for(int i =0;i<result.size();i++){
            if(zero !=0 && nums[i]!=0){
                result[i] != 0;
                continue;
            }else if(zero !=0 && nums[i] == 0){
                result[i] = mul;
                continue;
            }
            result[i] = mul/nums[i];
        }
        return result;
    }
};
View Code

1、关键在于能否想出0的情况 

 

268. Missing Number https://leetcode.com/problems/missing-number/description/

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size();i++){
            if(nums[i] != i)
                return i;
        }
        return nums.size();
    }
};
View Code

1、优化方法、将所有值和0-9全部异或一遍,如果重复出现则一定清0、求和再相见

 

414. Third Maximum Number https://leetcode.com/problems/third-maximum-number/description/

class Solution {
public:
    int thirdMax(vector<int>& nums) {
    long long m1 = (long long)INT_MIN - 1;
    long long m2 = (long long)INT_MIN - 2;
    long long m3 = (long long)INT_MIN - 3;
    int times = 0;
    for (int i = 0; i<nums.size(); i++) {
        if (nums[i]>m1) {
            times++;
            m3 = m2;
            m2 = m1;
            m1 = nums[i];
        }
        else if (nums[i]<m1 && nums[i]>m2) {
            times++;
            m3 = m2;
            m2 = nums[i];
        }
        else if (nums[i]<m2 && nums[i]>m3) {
            times++;
            m3 = nums[i];
        }
    }
    if(times < 3)
        return m1;
    return m3;
}
};
View Code

1、如何处理越界的问题

 

442. Find All Duplicates in an Array https://leetcode.com/problems/find-all-duplicates-in-an-array/description/

class Solution {
public:
    vector<int> findDuplicates(vector<int>& nums) {
        vector<int> res;
        for(int i = 0; i < nums.size(); i ++){
            nums[abs(nums[i])-1] = -nums[abs(nums[i])-1];
            if(nums[abs(nums[i])-1] > 0) res.push_back(abs(nums [i]));
        }
        return res;
    }
};
View Code

巧妙的方法

 

448. Find All Numbers Disappeared in an Array https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/description/

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        vector<int> result;
        for(int i=0;i<nums.size();i++){
            int pos = abs(nums[i]) -1;
            nums[pos] = abs(nums[pos])*-1;
        }
        for(int i =0;i<nums.size();i++){
            if(nums[i] >0) result.push_back(i+1);
        }
        return result;
    }
};
View Code

同上的方法

 

495. Teemo Attacking https://leetcode.com/problems/teemo-attacking/description/

class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) {
        if(timeSeries.size()==0) return 0;
        int pos1 = timeSeries[0];
        int pos2 = timeSeries[0];
        int result = 0;
        for(int i=1; i<timeSeries.size(); i++){
            if(timeSeries[i]>timeSeries[i-1]+duration){
                result = result + pos2 - pos1 + duration;
                pos1 = timeSeries[i];
                pos2 = timeSeries[i];
            }else{
                pos2 = timeSeries[i];
            }
        }
        return result + pos2 - pos1 + duration;
    }
};
View Code

思路和合并区间那道题一样,忘了是哪题了,主要需要注意怎么简化代码

 

6、其他

寻找一个数组中最大子片段

53. Maximum Subarray https://leetcode.com/problems/maximum-subarray/description/

    int maxSubArray(vector<int>& nums) {
        int max = INT_MIN;
        int current = 0;
        for(int i =0;i<nums.size();i++){
            current = current + nums[i];
            if(current > max)
                max = current;
            if(current < 0)
                current = 0;
        }
        return max;
    }
View Code

 

75. Sort Colors https://leetcode.com/problems/sort-colors/discuss/26474/Sharing-C++-solution-with-Good-Explanation

思路是维持两个位置,分别为0的结束位置和2的开始位置,遍历时如果碰到0则和前面的位置交换,碰到2则和后面的位置交换

    void sortColors(vector<int>& nums) {
        int pos0 = 0;
        int pos1 = 0;
        int pos2 = nums.size()-1;
        while(pos1<=pos2){
            if(nums[pos1] == 0){
                swap(nums[pos0], nums[pos1]);
                ++pos0;
                ++pos1;
            }else if(nums[pos1] == 2){
                swap(nums[pos1], nums[pos2]);
                --pos2;
            }else{
                ++pos1;
            }
        }
    }
View Code

1、在mid和first交换的时候需要将mid和first同时++,而不是只++mid,因为在pos0到pos1这段是只有1的,因为0被交换到前面,2被交换到后面

 

119. Pascal's Triangle II https://leetcode.com/problems/pascals-triangle-ii/description/

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> result(rowIndex+1,1);
        for(int i=3;i<=rowIndex+1;i++){
            for(int j=i-2;j>0;j--){
                result[j] = result[j]+result[j-1];
            }
        }
        return result;
    }
};
View Code

既然正向会覆盖,则逆向来赋值

 

120. Triangle https://leetcode.com/problems/triangle/description/

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        for(int i=triangle.size()-2;i>=0;i--){
            for(int j=0;j<=i;j++){
                triangle[i][j] = triangle[i][j] + min(triangle[i+1][j+1],triangle[i+1][j]);
            }
        }
        return triangle[0][0];
    }
};
View Code

动态规划,从底部可以简化代码很多

 

121. Best Time to Buy and Sell Stock https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()==0) return 0;
        int low = INT_MAX;
        int max = 0;
        for(int i=0;i<prices.size();i++){
            if(prices[i]<low)
                low = prices[i];
            if(prices[i]-low > max)
                max = prices[i]-low;
        }
        return max;
    }
};
View Code

1、思路是遍历每一个位置的时候和前面的最小值相减

2、注意size等于0是为什么会错误

 

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        if(nums.empty())
        return 0;
        int maxMul=nums[0];
        int minMul=nums[0];
        int ans=nums[0];
        for(int i=1;i<nums.size();i++)
        {
            int a = maxMul*nums[i];  
            int b = minMul*nums[i];  
            maxMul=max(max(a,b),nums[i]);
            minMul=min(min(a,b),nums[i]);
            ans=max(ans,maxMul);
        }
        return ans;
    }
};
View Code

1、当累加值*当前值<当前值时可以更新位置

 

169. Majority Element https://leetcode.com/problems/majority-element/description/

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int count = 0;
        int major = 0;
        for(int i=0;i<nums.size();i++){
            if(count == 0){
                count++;
                major = nums[i];
            }else{
                if(nums[i] == major){
                    count++;
                }else{
                    count--;
                }
            }
        }
        return major;
    }
};
View Code

229. Majority Element II https://leetcode.com/problems/majority-element-ii/description/ 

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        vector<int> result;
        int major1 = 0;
        int major2 = 0;
        int count1 = 0;
        int count2 = 0;
        for(int i=0;i<nums.size();i++){
            if(count1 != 0 && major1 == nums[i]){count1++;continue;}
            if(count2 != 0 && major2 == nums[i]){count2++;continue;}
            if(count1 == 0){major1 = nums[i];count1++;continue;}
            if(count2 == 0){major2 = nums[i];count2++;continue;}
            count1--;
            count2--;
        }
        int num1 = count1;
        int num2 = count2;
        count1 = 0;
        count2 = 0;
        for(int i=0;i<nums.size();i++){
            if(num1>0){
                if(nums[i] == major1) count1++;
            }
            if(num2>0){
                if(nums[i] == major2) count2++;
            }
        }
        if(count1>nums.size()/3) result.push_back(major1);
        if(count2>nums.size()/3) result.push_back(major2);
        return result;
    }
};
View Code

2题的思路一样,使用1个计数器或是2个计数器,遍历一个元素就从中删除其他两个元素的计数

 

 217. Contains Duplicate https://leetcode.com/problems/contains-duplicate/description/

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        for(int i =1;i<nums.size();i++){
            if(nums[i] == nums[i-1])
                return true;
        }
        return false;
    }
};
View Code

 

228. Summary Ranges https://leetcode.com/problems/summary-ranges/description/

class Solution {
public:
    vector<string> summaryRanges(vector<int>& nums) {
        vector<string> result;
        for(int i=0;i<nums.size();i++){
            int begin = nums[i];
            while(i != nums.size()-1 && nums[i]+1 == nums[i+1]){
                i++;
            }
            int end = nums[i];
            if(begin != end){
                result.push_back(to_string(begin) + "->" + to_string(end));
            }else{
                result.push_back(to_string(begin));
            }
        }
        return result;
    }
};
View Code

 

 

 

 

二、复习

15

16

18

26

27

31

33

75

80

81

119

120

121

152

153

169

209

229

238

268

414

442

448

495

posted @ 2018-09-03 19:54  番茄汁汁  阅读(908)  评论(0编辑  收藏  举报