leetcode感想

来源:互联网 发布:淘宝自动充值平台利润 编辑:程序博客网 时间:2024/06/14 07:12

首次刷leetcode。写完两题easy和一题medium后感觉题目偏容易,准备挑战一下hard,选择的题目如下:

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:

nums1 = [1, 3]nums2 = [2]The median is 2.0

Example 2:

nums1 = [1, 2]nums2 = [3, 4]The median is (2 + 3)/2 = 2.5


第一反应是,这题不是重排序成一个数组然后取下标中间值就行了么,so easy。

然而注意到时间复杂度要求在O(log(m+n))以内,这题就有意思了。因为重新排序至少也要花费O(m+n)的时间,而要求的时间复杂度就限制了重新排序的可能。

想了一个多小时,发现同时丢掉中位数左边和右边的N个数对中位数是没有影响的,于是决定用二分法递归地来解决这个问题。思路是不停的丢弃中位数左右边的n个数,直到有一个数组里只有一个数,开始计算中位数,运算结束。

另外在跑测试用例的时候遇到了一些特殊情况,又增加了一些特殊情况的判断。最终得到代码如下:

double median2c(int* nums, int numsSize){    if(numsSize%2==0)    {        return (nums[numsSize/2-1]+nums[numsSize/2])/2.0;    }    else if(numsSize%2==1)    {        return (double)nums[numsSize/2];    }    return -1;}double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {    if(nums1Size==0) return median2c(nums2, nums2Size);    if(nums2Size==0) return median2c(nums1, nums1Size);        int cutlen;    if(nums1Size%2 == 0 && nums2Size%2 == 0)    {        if(nums1[nums1Size/2-1]<nums2[nums2Size/2-1] && nums1[nums1Size/2]>nums2[nums2Size/2])            return (nums2[nums2Size/2-1]+nums2[nums2Size/2])/2.0;        if(nums1[nums1Size/2-1]>nums2[nums2Size/2-1] && nums1[nums1Size/2]<nums2[nums2Size/2])            return (nums1[nums1Size/2-1]+nums1[nums1Size/2])/2.0;    }        if(nums1Size==1 && nums2Size==1)    {        return (nums1[0]+nums2[0])/2.0;    }    else if(nums1Size==1)    {        if(nums2Size%2 == 0)        {            if(nums1[0]<=nums2[nums2Size/2-1]) return nums2[nums2Size/2-1];            else if(nums1[0]>=nums2[nums2Size/2]) return nums2[nums2Size/2];            else if(nums1[0]>nums2[nums2Size/2-1] && nums1[0]<nums2[nums2Size/2]) return nums1[0];         }        else if(nums2Size%2 == 1)        {            if(nums1[0]<=nums2[nums2Size/2-1]) return (nums2[nums2Size/2-1]+nums2[nums2Size/2])/2.0;            else if(nums1[0]>=nums2[nums2Size/2+1]) return (nums2[nums2Size/2]+nums2[nums2Size/2+1])/2.0;            else if(nums1[0]>nums2[nums2Size/2-1] && nums1[0]<nums2[nums2Size/2+1]) return (nums1[0]+nums2[nums2Size/2])/2.0;         }    }    else if(nums2Size==1)    {        return findMedianSortedArrays(nums2, nums2Size, nums1, nums1Size);    }    else    {        cutlen = (nums1Size/2 > nums2Size/2) ? nums2Size/2 : nums1Size/2;                    if(median2c(nums1,nums1Size) > median2c(nums2,nums2Size))        {            nums2 = nums2 + cutlen;        }        else if(median2c(nums1,nums1Size) < median2c(nums2,nums2Size))        {            nums1 = nums1 + cutlen;        }        else if(median2c(nums1,nums1Size) == median2c(nums2,nums2Size))        {            return median2c(nums1,nums1Size);        }        nums1Size = nums1Size - cutlen;        nums2Size = nums2Size - cutlen;       // return findMedianSortedArrays(nums1, nums1Size, nums2, nums2Size);    }    return findMedianSortedArrays(nums1, nums1Size, nums2, nums2Size);}

编写过程耗时超过3个小时。但毕竟是我第一次在实际问题中用递归思想将一个O(n)复杂度的算法降为了O(log(n)),心里还是挺美滋滋的。毕竟几年前在算法导论上看到分治法、快速排序等算法时还只能感叹前人的智慧。提交成功之后点击more details,发现自己只超过了77%的人,也就是说还有23%的人有更快的算法。于是我抱着学习的心态点进了速度最快的代码——下面转折来了。“最快“的算法使用的居然是O(m+n)复杂度的重新排序方法!也就是本博客一开始说的so easy的方法。

当时就有点崩溃,点开其他各个运行速度的代码查看,无一例外全部是O(m+n)。我转念一想,返回了提交页面重新提交了我的代码。提交的第二次居然只超过了44%的人。而提交到第五次的时候,也就是写这篇博客之前,居然获得了这样的结果:


??WTF?这算是leetcode颁发的安慰奖吗?


不管怎么样,通过这次刷题,得到了如下结论:

1.leetcode是一个适合练习编程语言而不是算法的地方。毕竟不合算法要求的代码提交也能通过,并且也有一定几率获得较好的运行时间结果。

2.代码的运行时间是在一定分布内随机波动的。不要太在意这个扯淡的submission detail。

3.有没有人能推荐个更靠谱点算法练习学习的网站?


原创粉丝点击