LeetCode刷题日记

排序

快排

第k个最小值

class Solution {
public:
    vector<int> smallestK(vector<int>& arr, int k) {
        vector<int> result;
        if (k <= 0 || arr.empty())
            return result; // 处理边界情况
        quicksort(arr, 0, arr.size() - 1, k);
        result.assign(arr.begin(), arr.begin() + k); // 复制前k个元素到结果
        return result;
    }
    void quicksort(vector<int>& arr, int l, int r, int k) {
        if (l < r) {                        // 确保左指针小于右指针
            int pos = partition(arr, l, r); // 获取分区位置
            if (pos == k - 1) { // 如果分区位置正好是第K小的位置
                // 已经找到第K小的元素,不需要进一步排序
                return;
            } else if (pos > k - 1) {
                // 如果第K小的元素在左分区,则递归左分区
                quicksort(arr, l, pos - 1, k);
            } else {
                // 否则,递归右分区
                quicksort(arr, pos + 1, r, k);
            }
        }
    }

    // 分区
    int partition(vector<int>& nums, int low, int high) {
        // 以第1位元素为基准数
        int pivot = nums[low];

        int i = low, j = high;
        while (i < j) {
            // 从右向左找到第1个小于基准数的元素
            while (i < j && nums[j] >= pivot) {
                j--;
            }
            // 从左向右找到第1个大于基准数的元素
            while (i < j && nums[i] <= pivot) {
                i++;
            }
            // 交换元素
            swap(nums[i], nums[j]);
        }
        // 将基准数放到正确位置上
        swap(nums[j], nums[low]);
        return j; // 返回基准元素的索引位置
    }
};

要点:

①分区函数返回基准值位置,根据分区位置与k的关系,判断是否再进行递归

②分区时,采用双指针的方法;将基准放到正确位置上,要注意;如果是以第一个元素作为基准数,那么一定是先从右到左找小于基准数的元素。(如果先从左到右,会出错,即把大数换到了第一位)

滑动窗口

最大连续1的个数

法一:前缀和

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int n = nums.size();
        int left = 0, lsum = 0, rsum = 0;
        int ans = 0;
        for (int right = 0; right < n; ++right) {
            rsum += 1 - nums[right];
            while (lsum < rsum - k) {
                lsum += 1 - nums[left];
                ++left;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};

要点:

①使用双指针滑动窗口。因为只有0和1,分别计算两个指针的前缀和,即可得到1的个数。(想得到零的个数,即 前缀和 += 1-nums[i] );

②使得两个前缀和(0的个数)之差小于等于k即可满足要求。

③右指针遍历,得到右指针前缀和,循环判断左指针前缀和是否满足要求,不满足,左指针前缀和++,左指针++;比较 ans和(r-l+1); 注意:判断满足要求的是 right 和 left-1指针的前缀和之差。所以先前缀和+=,再左指针++。

法二:记录零的个数

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int ans = 0;
        int zero_count = 0;
        int l=0;
        int r=0;
        while(r<nums.size()){
            if(!nums[r]){
                zero_count++;
            }
            if(zero_count>k){
                if(!nums[l]){
                    zero_count--;
                }
                    l++;
            }
            ans = max(ans,r-l+1);
            r++;
        }
        return ans;
    }
};

要点:

①每次都要判断,计数是否大于k,使左指针移动到满足条件的位置。

②先选择ans,再r++。否则会导致结果+1。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值