leetcode题解日练--2016.9.17

平常心

今日题目:

1、两个有序数组的中位数

2、找到两个数组中最小的k对最小和

今日摘录:

天上浮云如白衣,斯须改变如苍狗。——杜甫《何叹》

4. Median of Two Sorted Arrays | Difficulty: 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

tag:数组|二分|分治
题意:先给定两个数组,求它们的中位数,复杂度O(log (m+n)).

思路:
1、找中位数就是在两个数组中各自找到一个i、j元素作为分割线,分割线需要满足三个方程:
i+j=(nums1.size()+nums2.size()+1)/2 —> 二分去搜索i.j=(nums1.size()+nums2.size()+1)/2-i
nums1[i-1]<=nums2[j] (前提i-1和j不越界)
nums2[j-1]<=nums1[i] (前提j-1和i不越界)
当找到满足条件的i,j时候就返回,
否则如果nums1[i-1]

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size(),len2 = nums2.size();
        if(len1>len2)   return findMedianSortedArrays(nums2,nums1);
        int halfLen = (len1+len2+1)/2;
        int iLeft = 0,iRight = len1;
        double maxLeft = INT_MIN,minRight = INT_MAX;
        while(iLeft<=iRight)
        {
            int i = iLeft+(iRight-iLeft)/2;
            int j = halfLen-i;
            if(j>0 && i1])
                iLeft = i+1;
            else if(i>0 && j1])
                iRight = i-1;
            else
                {
                    if(i==0)
                        maxLeft = nums2[j-1];
                    else if(j==0)
                        maxLeft = nums1[i-1];
                    else
                        maxLeft = max(nums1[i-1],nums2[j-1]);
                    if((len1+len2)%2==1)
                        return maxLeft;
                    else if(i==len1)
                        minRight = nums2[j];
                    else if (j==len2)
                        minRight = nums1[i];
                    else
                        minRight = min(nums1[i],nums2[j]);
                    return (maxLeft+minRight)/2;
                }
        }
        return -1;
    }
};

结果:29ms
2、一样的思想,转换成找两个数组中的第K大数。
这里偶数个数的情况下要调用两次函数,可以改成加如一个标志位来做。

class Solution {
public:
    double findLargestK(const vector<int>&nums1,const vector<int>& nums2,int len1,int len2,int k)
    {
        int iLeft = 0,iRight = len1;
        double res =0;
        while(iLeft<=iRight)
        {
            int i = iLeft+(iRight-iLeft)/2;
            int j = k-i;

            if(j>len2 ||j>0 && i1])
                iLeft = i+1;
            else if(i>len1 || i>0 && j1])
                iRight = i-1;
            else
                {
                    if(i==0)
                        res = nums2[j-1];
                    else if(j==0)
                        res = nums1[i-1];
                    else
                        res = max(nums1[i-1],nums2[j-1]);
                    return res;
                }
        }
        return -1;

    }

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {

        int len1 = nums1.size(),len2 = nums2.size();
        if(len1>len2)   return findMedianSortedArrays(nums2,nums1);

        int totalLen = len1+len2;
        if(totalLen%2==1)   return findLargestK(nums1,nums2,len1,len2,totalLen/2+1);
        else    return (findLargestK(nums1,nums2,len1,len2,totalLen/2)+ findLargestK(nums1,nums2,len1,len2,totalLen/2+1))/2;
    }
};        

结果:62ms

373. Find K Pairs with Smallest Sums | Difficulty: Medium

You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.

Define a pair (u,v) which consists of one element from the first array and one element from the second array.

Find the k pairs (u1,v1),(u2,v2) …(uk,vk) with the smallest sums.

Example 1:
Given nums1 = [1,7,11], nums2 = [2,4,6], k = 3

Return: [1,2],[1,4],[1,6]

The first 3 pairs are returned from the sequence:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
Example 2:
Given nums1 = [1,1,2], nums2 = [1,2,3], k = 2

Return: [1,1],[1,1]

The first 2 pairs are returned from the sequence:
[1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]
Example 3:
Given nums1 = [1,2], nums2 = [3], k = 3

Return: [1,3],[2,3]

All possible pairs are returned from the sequence:
[1,3],[2,3]

tag:堆

题意:找到两个数组中最小的k对最小和
思路:
1、建立一个最小堆,这样每次堆顶都是我们需要找的一对数,但是现在不是对一个数字进行排序,而是对一对数字的和进行排序,因此需要自定义一个比较函数,自己定义一个堆处理成对的数据结构。
每次我们取出了(i,j)对元素之后,接下来按理需要放进去(i+1,j)和(i,j+1)。但是在(i+1,j-1)判断的时候同样会加入(i+1,j),这样就重复了。那怎么解决呢?
除了第一行元素加入右边和下面的元素之外,其他元素都只加入下面的元素。

class Solution {
public:
    vectorint, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
        vectorint ,int> > res;
        if (nums1.empty() || nums2.empty() || k <= 0)
            return res;
        //创建一个堆
        auto compare = [&nums1,&nums2](pair<int,int> a,pair<int,int>b){
            return nums1[a.first]+nums2[a.second] > nums1[b.first]+nums2[b.second];
        };
        priority_queue< pair<int,int>,vectorint ,int> >, decltype(compare) > heap(compare);
        heap.emplace(0,0);
        while(k-- && !heap.empty())
        {
            auto index = heap.top();
            heap.pop();
            res.emplace_back(nums1[index.first],nums2[index.second]);
            if(index.first+11,index.second);
            if(index.first==0 && index.second+11);
        }
        return res;
    }
};

结果:16ms

你可能感兴趣的:(leetcode)