只能说配合chatgpt debug+学习代码真香!要好好利用chatgpt提升自己的项目完成能力和算法能力!
Leetcode 第四题
这道题我倒是有思路,思路非常简单粗暴,就是先合并数组,用sort排序后求解中位数。但是一直AC不了,现在附上我的代码和经过chatgpt改动的代码
我原来的代码:
#include<iostream>
#include<algorithm>
#include <vector>
using namespace std;
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = sizeof(nums1) / sizeof(nums1[0]);
int m = sizeof(nums2) / sizeof(nums2[0]);
for (int i = 0; i < m; i++) {
nums1[n + i] = nums2[i];
}
int k = sizeof(nums1) / sizeof(nums1[0]);
sort(nums1.begin(), nums1.begin()+ m + n);
if (k % 2 != 0)
{
cout << nums1[k / 2 + 1] << endl;
}
else {
cout << (nums1[k / 2] + nums1[k / 2 + 1]) / 2.0 << endl;
}
return 0;
}
}
chatgpt评价这个代码的缺点:
我记得sizeof(num)/sizeof(num[0])的方式也可以用于计算数组长度,因此我把自己的疑问讲了出来,chatgpt回答如下:
也就是说不是vector不能使用sort,而是vector无法正确使用sizeof!
之后chatgpt给出了它改动后的代码:
#include<iostream>
#include<algorithm>
#include <vector>
using namespace std;
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
int m = nums2.size();
nums1.resize(n + m);
for (int i = 0; i < m; i++) {
nums1[n + i] = nums2[i];
}
int k = n + m;
sort(nums1.begin(), nums1.end());
if (k % 2 != 0)
{
return nums1[k / 2];
}
else {
return (nums1[k / 2 - 1] + nums1[k / 2]) / 2.0;
}//数组是从零开始!!!!
}
};
这次就正常运行了
在正常运行之后,我害怕算法的时间复杂度不满足要求,所以也问了这个问题
可以看出我的算法并不完全符合题意(虽然并没有超时)
要如何使时间复杂度满足O(log(m+n))呢?我的想法是不用合并数组,直接寻找中位数。查找方面我们可以采用二分查找的算法。
此时时间复杂度O(log(min(n1, n2))),n1 和 n2 分别为两个数组的长度。空间复杂度为 O(1),因为算法只使用了常数级别的额外空间。
#include<algorithm>
using namespace std;
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
const int n1 = nums1.size();
const int n2 = nums2.size();
if (n1 > n2) return findMedianSortedArrays(nums2, nums1);
const int k = (n1 + n2 + 1) / 2;
int left = 0;
int right = n1;
while (left < right) {
const int m1 = left + (right - left) / 2;
const int m2 = k - m1;
if (nums1[m1] < nums2[m2 - 1])
left = m1 + 1;
else
right = m1;
}
const int m1 = left;
const int m2 = k - left;
const int c1 = max(m1 <= 0 ? INT_MIN : nums1[m1 - 1],
m2 <= 0 ? INT_MIN : nums2[m2 - 1]);
if ((n1 + n2) % 2 == 1)
return c1;
const int c2 = min(m1 >= n1 ? INT_MAX : nums1[m1],
m2 >= n2 ? INT_MAX : nums2[m2]);
return (c1 + c2) * 0.5;
}
};
具体来说,该算法的思路是将两个数组分别划分为两部分,使得左半部分的长度之和等于右半部分的长度之和,且左半部分的最大值不大于右半部分的最小值。这样,中位数就可以通过左半部分的最大值和右半部分的最小值计算得出。为了实现这个思路,算法使用了二分查找的方法。具体的步骤如下:
我一直不太明白INT_MIN和INT_MAX这样的量,所以我问了chatgpt。
这段代码使用了 INT_MIN 和 INT_MAX 这两个常量。它们是 C++ 标准库头文件 <limits.h> 或 <climits> 中定义的常量,分别表示 int 类型能够存储的最小值和最大值。
也就是
const int c1 = max(m1 <= 0 ? INT_MIN : nums1[m1 - 1],
m2 <= 0 ? INT_MIN : nums2[m2 - 1]);
这段代码,是在防止m1和m2小于0从而导致数组越界的情况,如果越界,则使用INT_MIN和INT_MAX这样的值。
我自己的算法:
将两个数组合并,然后排序求中位数,时间复杂度为O((m+n)log(m+n)),空间复杂度为O(m+n),相对而言时间和空间复杂度都较高。
符合题意的算法:
采用二分查找的思路,时间复杂度为O(log(min(m, n))),空间复杂度为O(1),可以看作是比较高效的算法。