算法设计与分析 hws & labs

这门课的课本是《算法导论》,hws 就是老师布置的一些课后作业,labs 就是提供的五个实验,在这里记录的目的主要是帮助自己理解算法的设计与分析,而不仅仅是作为应付作业的需求。

Lab 1 Division and Conquer

分治法,主要思想是讲问题分解为子问题,当子问题足够在 O(n) 以内的时间复杂度解决时即可返回。
leetcode 4.寻找两个正序数组的中位数

  1. 首先将为题转变为寻找两个正序数组的第 k 小个数
  2. 分解为子问题:给定两个数组的起始位置,从此位置向后寻找第 k 小个数
  3. 子问题解决方式:每次考察两个数组中距离起始位置 k / 2 的数的大小,对比此值较小的那个数组的前 k / 2 个(数必定会存在于最终的 k 个数中,因此可以去掉这 k / 2 个(也有可能全被抛弃)数,直接从剩余的所有树中寻找第 k - (抛弃的个数) 小的数
点击查看代码
class Solution {
public:
    int findKth(vector<int>& nums1, int i, vector<int>& nums2, int j, int k) {
        if (nums1.size() - i > nums2.size() - j) {
            return findKth(nums2, j, nums1, i, k);
        }
        if (nums1.size() == i)
            return nums2[j + k - 1];
        if (k == 1)
            return min(nums1[i], nums2[j]);
        
        int si = min((int)nums1.size(), i + k / 2), sj = j + k / 2;
        if (nums1[si - 1] > nums2[sj - 1]) {
            return findKth(nums1, i, nums2, sj, k - k / 2);
        } else {
            return findKth(nums1, si, nums2, j, k - (si - i));
        }
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int tot = nums1.size() + nums2.size();
        if (tot % 2 == 0) {
            int l = findKth(nums1, 0, nums2, 0, tot / 2);
            int r = findKth(nums1, 0, nums2, 0, tot / 2 + 1);
            return (l + r) / 2.0;
        } else 
            return findKth(nums1, 0, nums2, 0, tot / 2 + 1);
    }
};

Leetcode53. 最大子数组和
这个题目的思路是来自于课本第四章分治策略的一个例子,原例子讲的是股票市场的最大交易方式,这个题目具有同样的思路:
给定数组和左右边界,以其中点为分割,则最大子数组要么存在于中点左侧(包括中点),要么存在于中点右侧(包括中点),要么跨越中点。
以此为子问题,用左右边界来分解问题,其中跨越中点的最大子数组和要用到一次遍历,分别计算 l 到 mid 和 mid 到 r 两部分的最大和。

点击查看代码
class Solution {
public:
    int cal(vector<int>& nums, int l, int r) {
        if (l == r)
            return nums[l];
        int mid = (l + r) >> 1;

        int lmax = nums[mid], rmax = nums[mid + 1];
        int lsum = 0, rsum = 0;

        for (int i = mid; i >= l; i --) {
            lsum += nums[i];
            lmax = max(lmax, lsum);
        }

        for (int i = mid + 1; i <= r; i ++) {
            rsum += nums[i];
            rmax = max(rmax, rsum);
        }

        int lr = max(cal(nums, l, mid), cal(nums, mid + 1, r));
        return max(lr, lmax + rmax);
    }

    int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        return cal(nums, 0, n - 1);
    }
};

Lab2 排序算法练习——快排 + 计数排序

posted @ 2023-03-25 19:27  ImproperMelon  阅读(34)  评论(0)    收藏  举报