leetcode题解日练--2016.9.17

来源:互联网 发布:nemo软件 编辑:程序博客网 时间:2024/06/01 09:40

平常心

今日题目:

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 && i<len1 && nums1[i]<nums2[j-1])                iLeft = i+1;            else if(i>0 && j<len2 && nums2[j]<nums1[i-1])                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 && i<len1 && nums1[i]<nums2[j-1])                iLeft = i+1;            else if(i>len1 || i>0 && j<len2 && nums2[j]<nums1[i-1])                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:    vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {        vector<pair<int ,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>,vector<pair<int ,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+1<nums1.size())                heap.emplace(index.first+1,index.second);            if(index.first==0 && index.second+1<nums2.size())                heap.emplace(index.first,index.second+1);        }        return res;    }};

结果:16ms

0 0
原创粉丝点击