二、数组2(基础算法思路的应用与对撞指针)

二、数组2(基础算法思路的应用与对撞指针)

基础算法思路的应用

75. 颜色分类

  • 解法一

计算每个颜色的个数,然后填充数组

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int count[3] = {0};
        for(int i=0; i<nums.size(); ++i){
            assert(nums[i]>=0 && nums[i]<=2);
            ++count[nums[i]];
        }
        int index=0;
        // for(int i=0; i<count[0]; ++i){
        //     nums[index] = 0;
        //     ++index;
        // }
        // for(int i=0; i<count[1]; ++i){
        //     nums[index] = 1;
        //     ++index;
        // }
        // for(int i=0; i<count[2]; ++i){
        //     nums[index] = 2;
        //     ++index;
        // }
        for(int i=0; i<3; ++i){
            for(int j=0; j<count[i]; ++j){
                nums[index] = i;
                ++index;
            }
        }
    }
};
  • 解法2

利用三路快排

class Solution {
public:
    void sortColors(vector<int>& nums) {
        // 采用三路快排的思想进行排序

        int v = 1;
        // <v [l, lt]
        // ==v [lt+1, i)
        // >v [gt, r]
        int lt=-1;
        int gt=nums.size();
        int i=0;
        while(i<gt){
            if(nums[i]<v){
                swap(nums[lt+1], nums[i]);
                ++lt;
                ++i;
            }
            else if(nums[i]>v){
                swap(nums[gt-1], nums[i]);
                --gt;
            }
            else{  // nums[i] == v
                ++i;
            }
        }
    }
};

88. 合并两个有序数组

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        // 开辟一个辅助数组 复制nums1 然后再将辅助数组和nums2合并到nums1
        vector<int> aux(nums1.begin(), nums1.begin()+m);
        
        int j=0;  // aux
        int k=0;  // nums2
        for(int i=0; i<nums1.size(); ++i){
            if(j>=m){
                nums1[i] = nums2[k];
                ++k;
            }
            else if(k>=n){
                nums1[i] = aux[j];
                ++j;
            }
            else if(aux[j]<nums2[k]){
                nums1[i]=aux[j];
                ++j;
            }
            else if(aux[j]==nums2[k]){
                nums1[i] = aux[j];
                ++i;
                nums1[i] = nums2[k];
                ++j;
                ++k;
            }
            else{  // aux[j]>nums2[k]
                nums1[i] = nums2[k];
                ++k;
            }
        }
    }
};

215. 寻找第K大的元素

利用双路快排解法

class Solution {
public:
    int __partition(vector<int>& nums, int l, int r){
        swap(nums[l], nums[rand()%(r-l+1)+l]);
        int v = nums[l];

        // <v [l+1, i)
        // >v (j, r]
        int j=r;
        int i=l+1;
        while(true){
            while(i<=r && nums[i]<v)
                ++i;
            while(j>=l+1 && nums[j]>v)
                --j;
            if(i>j)
                break;
            swap(nums[i], nums[j]);
            ++i;
            --j;
        }
        swap(nums[l], nums[j]);
        return j;
    }

    int __findKthLargest(vector<int>& nums, int l, int r, int k){
        // 利用双路快排进行寻找第k大元素

        if(l>r)
            return 0;

        int p=__partition(nums, l, r);
        if(p==nums.size()-k){
            return p;
        }
        else if(p<nums.size()-k)
            return __findKthLargest(nums, p+1, r, k);
        else // p>nums.size()-k
            return __findKthLargest(nums, l, p-1, k);
    }
    int findKthLargest(vector<int>& nums, int k) {
        srand(time(NULL));
        return nums[__findKthLargest(nums, 0, nums.size()-1, k)];
    }
};

对撞指针

167. 两数之和II-输入有序数组
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        
        // 对撞指针
        int l=0;
        int r=numbers.size()-1;

        while(l<r){
            if(numbers[l]+numbers[r]==target){
                int res[2] = {l+1, r+1};
                return vector<int>(res, res+2);
            }
            else if(numbers[l]+numbers[r]<target){
                ++l;
            }
            else{
                --r;
            }
        }

        return {};
    }
};

125. 验证回文串

class Solution {
public:
    
    bool isPalindrome(string s) {
        int j=0;
        for(int i=0;i<s.size(); ++i){
            if(s[i]>=65&&s[i]<=90){
                s[j] = s[i];
                ++j;
            }
            else if(s[i]>=97&&s[i]<=122){
                s[j] = s[i] - 32;
                ++j;
            }
            else if(s[i]>=48&&s[i]<=57){
                s[j] = s[i];
                ++j;
            }
        }
        
        // 对撞指针
        int l=0;
        int r=j-1;
        while(l<r){
            if(s[l] == s[r]){
                ++l;
                --r;
            }
            else
                return false;
        }
        return true;
    }
};

344. 反转字符串

class Solution {
public:
    void reverseString(vector<char>& s) {
        int l=0;
        int r=s.size()-1;
        while(l<r){
            swap(s[l], s[r]);
            ++l;
            --r;
        }
    }
};

11. 盛最多水的容器

暴力解法超时
巧妙的双指针解法

class Solution {
public:
    int maxArea(vector<int>& height) {
        // 双指针 从两端遍历
        // 由于从两端往中间移动,底总是变小的
        // 因此,总是要保证找到比较高的位置
        // 因此左边矮,就把左边往右移,右边同理

        // 理解:一个高的一个矮的进行计算面积,隐含着从矮的到高的这个区间所有的当前矮墙与其它墙的组合已经不成立
        // 因而计算完当前组合后,就可以丢弃矮墙,进行剩下的组合计算
        int l = 0;
        int r = height.size()-1;
        int max_area = 0;
        
        while(l<r){
            max_area = max(max_area, (r-l)*min(height[l], height[r]));
            if(height[l]>height[r])
                --r;
            else
                ++l;
        }

        return max_area;

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值