leetcode感想

首次刷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.有没有人能推荐个更靠谱点算法练习学习的网站?


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值