【CODE】BIT & mergeSort & Sort & TopK

目录

493. Reverse Pairs

315. Count of Smaller Numbers After Self

327. Count of Range Sum

148. Sort List

75. Sort Colors

324. Wiggle Sort II

215. Kth Largest Element in an Array

347. Top K Frequent Elements

692. Top K Frequent Words

973. K Closest Points to Origin

1054. Distant Barcodes

378. Kth Smallest Element in a Sorted Matrix

373. Find K Pairs with Smallest Sums

719. Find K-th Smallest Pair Distance

658. Find K Closest Elements


493. Reverse Pairs

Hard

702107Add to ListShare

Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j].

You need to return the number of important reverse pairs in the given array.

Example1:

Input: [1,3,2,3,1]
Output: 2

Example2:

Input: [2,4,3,5,1]
Output: 3

Note:

  1. The length of the given array will not exceed 50,000.
  2. All the numbers in the input array are in the range of 32-bit integer.
class Solution {
public:
    int lowerbit(int x){
        return x&(-x);
    }
    void add(int x,vector<int> &c){
        while(x<c.size()){
            c[x]+=1;
            x+=lowerbit(x);
        }
        return;
    }
    int getSum(int x,vector<int> c){
        int res=0;
        while(x>0){
            res+=c[x];
            x-=lowerbit(x);
        }
        return res;
    }
    int reversePairs(vector<int>& nums) {
        vector<int> value=nums;
        sort(value.begin(),value.end());
        vector<int> c(nums.size()+1);
        unordered_map<int,int> mp;
        for(int i=0;i<value.size();i++){
            mp[value[i]]=i+1;
        }
        int res=0;
        for(int i=nums.size()-1;i>=0;i--){
            res+=getSum(lower_bound(value.begin(),value.end(),nums[i]/2.0)-value.begin(),c);
            add(mp[nums[i]],c);
        }
        return res;
    }
};
class Solution {
public:
    int mergeSort(vector<int> &nums,int left,int right){
        if(left>=right) return 0;
        int mid=left+(right-left)/2;
        int res=mergeSort(nums,left,mid)+mergeSort(nums,mid+1,right);
        for(int i=left,j=mid+1;i<=mid;i++){
            while(j<=right && nums[i]/2.0 > nums[j]) j++;
            res+=j-(mid+1);
        }
        sort(nums.begin()+left,nums.begin()+right+1);
        return res;
    }
    int reversePairs(vector<int>& nums) {
        return mergeSort(nums,0,nums.size()-1);
    }
};
  • 归并思想

315. Count of Smaller Numbers After Self

Hard

176269Add to ListShare

You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].

Example:

Input: [5,2,6,1]
Output: [2,1,1,0] 
Explanation:
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.
class Solution {
public:
    void add(int x,vector<int>& c){
        while(x<c.size()){
            c[x]+=1;
            x+=x&(-x);
        }
        return;
    }
    int getSum(int x,vector<int> c){
        int res=0;
        while(x>0){
            res+=c[x];
            x-=x&(-x);
        }
        return res;
    }
    vector<int> countSmaller(vector<int>& nums) {
        vector<int> value=nums;
        sort(value.begin(),value.end());
        unordered_map<int,int> mp;
        for(int i=0;i<value.size();i++){
            mp[value[i]]=i+1;
        }
        vector<int> c(nums.size()+1);
        vector<int> res(nums.size());
        for(int i=nums.size()-1;i>=0;i--){
            res[i]=getSum(lower_bound(value.begin(),value.end(),nums[i])-value.begin(),c);
            add(mp[nums[i]],c);
        }
        return res;
    }
};
  • Runtime: 640 ms, faster than 9.17% of C++ online submissions for Count of Smaller Numbers After Self.
  • Memory Usage: 326.6 MB, less than 8.33% of C++ online submissions for Count of Smaller Numbers After Self.
class Solution {
public:
    vector<int> countSmaller(vector<int>& nums) {
        vector<int> res(nums.size());
        deque<int> de;
        for (int i = nums.size() - 1; i >= 0;i--){
            deque<int>::iterator it = lower_bound(de.begin(), de.end(), nums[i]);
            res[i] = it - de.begin();
            de.insert(it, nums[i]);
        }
        return res;
    }
};
  • Runtime: 132 ms, faster than 33.28% of C++ online submissions for Count of Smaller Numbers After Self.
  • Memory Usage: 10.3 MB, less than 83.33% of C++ online submissions for Count of Smaller Numbers After Self.

327. Count of Range Sum

Hard

58175Add to ListShare

Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.
Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive.

Note:
A naive algorithm of O(n2) is trivial. You MUST do better than that.

Example:

Input: nums = [-2,5,-1], lower = -2, upper = 2,
Output: 3 
Explanation: The three ranges are : [0,0], [2,2], [0,2]and their respective sums are: -2, -1, 2
class Solution {
public:
    int countRangeSum(vector<int>& nums, int lower, int upper) {
        multiset<long long> sums;
        sums.insert(0);
        long long sum=0;
        int res=0;
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
            res+=distance(sums.lower_bound(sum-upper),sums.upper_bound(sum-lower));
            sums.insert(sum);
        }
        return res;
    }
};

148. Sort List

Medium

2142107Add to ListShare

Sort a linked list in O(n log n) time using constant space complexity.

Example 1:

Input: 4->2->1->3
Output: 1->2->3->4

Example 2:

Input: -1->5->3->4->0
Output: -1->0->3->4->5
  • 单链表排序
#include<iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
#include<deque>
#include<set>
using namespace std;
typedef struct ListNode{
    int value;
    ListNode *next;
} ListNode;
ListNode *createList(){
    int n;
    cin >> n;
    ListNode *HEAD =(ListNode *)malloc(sizeof(ListNode));
    ListNode *head = (ListNode *)malloc(sizeof(ListNode));
    for (int i = 0; i < n;i++){
        ListNode *tmp = (ListNode *)malloc(sizeof(ListNode));
        int value;
        cin >> value;
        tmp->value = value;
        tmp->next = NULL;
        if(i==0) head=tmp;
        else HEAD->next=tmp;
        HEAD = tmp;
    }
    return head;
}
ListNode *merge(ListNode *head1,ListNode *head2){
    if(head1==NULL) return head2;
    if(head2==NULL) return head1;
    ListNode *head = NULL;
    if(head1->value<=head2->value){
        head=head1;
        head1 = head1->next;
    }else{
        head = head2;
        head2 = head2->next;
    }
    ListNode *HEAD = head;
    while (head1 && head2){
        if (head1->value <= head2->value){
            head->next = head1;
            head1 = head1->next;
            head = head->next;
        }
        else{
            head->next = head2;
            head2 = head2->next;
            head = head->next;
        }
    }
    if(head1) head->next=head1;
    if(head2) head->next=head2;
    return HEAD;
}
ListNode *mergeSort(ListNode *head){
    if(head==NULL || head->next==NULL) return head;
    ListNode *fast = head->next, *slow = head;
    while(fast && fast->next){
        fast = fast->next->next;
        slow = slow->next;
    }
    ListNode *headb = slow->next;
    slow->next = NULL;
    return merge(mergeSort(head), mergeSort(headb));
}
void print(ListNode *head){
    while(head){
        cout << head->value << " ";
        head=head->next;
    }
    return;
}
int main(){
    ListNode *tmp=createList();
    tmp=mergeSort(tmp);
    print(tmp);
    system("pause");
    return 0;
}
  • Runtime: 52 ms, faster than 81.94% of C++ online submissions for Sort List.
  • Memory Usage: 15 MB, less than 15.00% of C++ online submissions for Sort List.
  • Next challenges:
  • Sort Colors
  • Insertion Sort List

75. Sort Colors

Medium

2494192Add to ListShare

Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note: You are not suppose to use the library's sort function for this problem.

Example:

Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]

Follow up:

  • A rather straight forward solution is a two-pass algorithm using counting sort.
    First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
  • Could you come up with a one-pass algorithm using only constant space?
  • 计数排序 // 快速排序的思想(cur指向当前遍历,low指向0,high指向2)
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int low=0,high=nums.size()-1,cur=0;
        while(cur<=high){
            if(nums[cur]==0) swap(nums[cur++],nums[low++]);
            else if(nums[cur]==1) cur++;
            else if(nums[cur]==2) swap(nums[cur],nums[high--]);
        }
        return ;
    }
};

324. Wiggle Sort II

Medium

859467Add to ListShare

Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]....

Example 1:

Input: nums = [1, 5, 1, 1, 6, 4]

Output: One possible answer is [1, 4, 1, 5, 1, 6]

Example 2:

Input: nums = [1, 3, 2, 2, 3, 1]

Output: One possible answer is [2, 3, 1, 3, 1, 2]

Note:
You may assume all input has valid answer.

Follow Up:
Can you do it in O(n) time and/or in-place with O(1) extra space?

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
/*Given an unsorted array nums, reorder it in-place 
such that nums[0] <= nums[1] >= nums[2] <= nums[3]....
For example, given nums = [3, 5, 2, 1, 6, 4], 
one possible answer is [1, 6, 2, 5, 3, 4].
1.先来看一种时间复杂度为O(nlgn)的方法,思路是先给数组排个序,
然后我们只要每次把第三个数和第二个数调换个位置,
第五个数和第四个数调换个位置,以此类推直至数组末尾,
这样就能完成摆动排序了。
2.这道题还有一种O(n)的解法,根据题目要求的
nums[0] <= nums[1] >= nums[2] <= nums[3]....,
可以总结出如下规律:
当i为奇数时,nums[i] >= nums[i - 1]
当i为偶数时,nums[i] <= nums[i - 1]
那么只要对每个数字(从后往前遍历),根据其奇偶性,跟其对应的条件比较,
如果不符合就和前面的数交换位置即可。*/
void wraggle1(vector<int> &nums){
    for (int i = nums.size() - 1; i >= 0;i--){
        if(i!=0 && i%2==0){
            if(nums[i]>nums[i-1]) swap(nums[i],nums[i-1]);
        }else if(i%2==1){
            if(nums[i-1]>nums[i]) swap(nums[i],nums[i-1]);
        }
    }
}
/*Given an unsorted array nums, reorder it 
such that nums[0] < nums[1] > nums[2] < nums[3]....
这道题给了我们一个无序数组,让我们排序成摆动数组,
满足nums[0] < nums[1] > nums[2] < nums[3]...,并给了我们例子。
我们可以先给数组排序,然后在做调整。调整的方法是找到数组的中间的数,
相当于把有序数组从中间分成两部分,
然后从前半段的末尾取一个,在从后半的末尾取一个,这样保证了第一个数小于第二个数,
然后从前半段取倒数第二个,从后半段取倒数第二个,这保证了第二个数大于第三个数,
且第三个数小于第四个数,以此类推直至都取完,参见代码如下:*/
void wraggle21(vector<int> &nums){
    sort(nums.begin(), nums.end());
    int left = 0, right = nums.size() - 1;
    int mid = left + (right - left) / 2;
    left = mid;
    vector<int> res;
    while(left>=0 && right>mid){
        res.push_back(nums[left--]);
        res.push_back(nums[right--]);
    }
    while(left>=0) res.push_back(nums[left--]);
    while(right>mid) res.push_back(nums[right--]);
    nums = res;
}
/*若使用O(1)的空间复杂度:
小的数字放在偶数位,大的数字放在奇数位
如何判断数字是大的还是小的:中位数比较
nth_element:找到容器中第n大的数,并放在第n位置上,
n位置前、后有序,总的无序.
拿出一个数和中位数进行比较,然后向指定位置上搬运,
这种操作好像在二分法中用的很多,但是,不同的是,
二分法中,是将数往左边和右边放,而此时我们是打算将数往奇偶位上移动,
所以,要区分索引的奇偶性。而这一步我们可以借用二分法中的大小指针法去做,
举个例子,我们可以把二分法中的小指针映射成奇数位,
把二分法张的大指针映射成偶数位,
要让一个数变成奇数,最好的办法就是: num*2+1。
而让一个奇数变成偶数的方法就是:对一个奇数取余。num%奇数。*/
void wraggle22(vector<int> &nums){
    if(nums.size()<2) return ;
    nth_element(nums.begin(), nums.begin() + nums.size() / 2, nums.end());
    int mid = nums[nums.size() / 2];
    #define A(i) nums[(2*i+1)%(nums.size()|1)]
    int j = 0, i = 0, k = nums.size() - 1;
    while(j<=k){
        if(A(j)>mid) swap(A(i++),A(j++));
        else if(A(j)<mid) swap(A(j),A(k--));
        else j++;
    }
    return;
}
int main(){
    vector<int> nums = {5,3,1,2,6,7,8,5,5};
    wraggle22(nums);
    for (int i = 0; i < nums.size();i++) cout<<nums[i]<<" ";
    system("pause");
    return 0;
} 

215. Kth Largest Element in an Array

Medium

2969209Add to ListShare

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Example 1:

Input: [3,2,1,5,6,4] and k = 2
Output: 5

Example 2:

Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4

Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.

class Solution {
public:
    int findKthLargest(vector<int>& nums,int k){
        int left=0,right=nums.size()-1;
        while(true){
            int pos=partition(nums,left,right);
            if(pos==k-1) return nums[pos];
            if(pos>k-1) right=pos-1;
            else left=pos+1;
        }
    }
    int partition(vector<int> &num,int left,int right){//降序
        int i=left+1,j=right;
        int tmp=num[left];
        while(i<=j){
            if(num[i]<tmp && num[j]>tmp) swap(num[i++],num[j--]);
            if(num[i]>=tmp) i++;
            if(num[j]<=tmp) j--;
        }
        swap(num[j],num[left]);
        return j;
    }
};
  • 快速排序思想

347. Top K Frequent Elements

Medium

2389160Add to ListShare

Given a non-empty array of integers, return the k most frequent elements.

Example 1:

Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]

Example 2:

Input: nums = [1], k = 1
Output: [1]

Note:

  • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
/*返回k个出现频率最高的元素,非空无序数组
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]*/
#include<iostream>
#include<vector>
#include<unordered_map>
#include<queue>
using namespace std;
/*1.使用map + priority_queue*/
vector<int> topKFrequent(vector<int>& nums, int k) {
    unordered_map<int, int> mp;
    for (int i = 0; i < nums.size();i++){
        mp[nums[i]]++;
    }
    priority_queue<pair<int, int> > q;
    unordered_map<int, int>::iterator it;
    vector<int> res;
    for (it = mp.begin(); it != mp.end();it++){
        q.push(make_pair(it->second, it->first));
    }
    while(k>0){
        k--;
        cout << k << endl;
        res.push_back(q.top().second);
        q.pop();
    }
    return res;
}
/*2.使用桶排序思想,额外维护一个二维数组,存放出现 i 次数的数字组成的数组*/
vector<int> topKFrequent(vector<int>& nums, int k) {
    unordered_map<int, int> mp;
    for (int i = 0; i < nums.size();i++){
        mp[nums[i]]++;
    }
    vector<vector<int>> bucket(nums.size() + 1);
    unordered_map<int, int>::iterator it;
    for(it=mp.begin();it!=mp.end();it++){
        bucket[it->second].push_back(it->first);
    } 
    vector<int> res;
    for(int i=nums.size();i>=0;i--){
        for (int j = 0; j < bucket[i].size();j++){
            res.push_back(bucket[i][j]);
        }
        if(res.size()==k) return res;
    }
    return res;
}
int main(){
    vector<int> num = {1, 1, 1, 2, 2, 3};
    vector<int> res = topKFrequent(num, 2);
    for (int i = 0; i < res.size(); i++){
        cout << res[i] << " ";
    }
    system("pause");
    return 0;
}

692. Top K Frequent Words

Medium

1304109Add to ListShare

Given a non-empty list of words, return the k most frequent elements.

Your answer should be sorted by frequency from highest to lowest. If two words have the same frequency, then the word with the lower alphabetical order comes first.

Example 1:

Input: ["i", "love", "leetcode", "i", "love", "coding"], k = 2
Output: ["i", "love"]
Explanation: "i" and "love" are the two most frequent words.Note that "i" comes before "love" due to a lower alphabetical order.

Example 2:

Input: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
Output: ["the", "is", "sunny", "day"]
Explanation: "the", "is", "sunny" and "day" are the four most frequent words,with the number of occurrence being 4, 3, 2 and 1 respectively.

Note:

  1. You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  2. Input words contain only lowercase letters.

Follow up:

  1. Try to solve it in O(n log k) time and O(n) extra space.
class Solution {
public:
    struct cmp_q{
        template <typename T, typename U>
        bool operator()(T const &left, U const &right){
            if (left.first == right.first)
                return left.second > right.second;
            return left.first < right.first;
        }
    };
    vector<string> topKFrequent(vector<string>& words, int k) {
        int n=words.size();
        vector<string> res;
        map<string,int> mp;
        for(int i=0;i<n;i++){
            mp[words[i]]++;
        }
        priority_queue<pair<int,string>,vector<pair<int,string> >,cmp_q > q;
        map<string,int>::iterator it;
        for(it=mp.begin();it!=mp.end();it++){
            q.push(make_pair(it->second,it->first));
        }
        for(int i=0;i<k;i++){
            res.push_back(q.top().second);
            q.pop();
        }
        return res;
    }
};
class Solution {
public:
    struct Node{
        int x;
        string y;
    };
    struct cmp_q{
        bool operator()(Node a,Node b){
            if(a.x==b.x) return a.y>b.y;
            else return a.x<b.x;
        }
    };
    vector<string> topKFrequent(vector<string>& words, int k) {
        int n=words.size();
        vector<string> res;
        map<string,int> mp;
        for(int i=0;i<n;i++){
            mp[words[i]]++;
        }
        priority_queue<Node,vector<Node>,cmp_q > q;
        map<string,int>::iterator it;
        for(it=mp.begin();it!=mp.end();it++){
            q.push({it->second,it->first});
        }
        for(int i=0;i<k;i++){
            res.push_back(q.top().y);
            q.pop();
        }
        return res;
    }
};
class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        unordered_map<string, int> mp;
        for (int i = 0; i < words.size();i++){
            mp[words[i]]++;
        }
        vector<priority_queue<string,vector<string>,greater<string> > >bucket(words.size()+1);
        //这里定义priority_queue的排序:默认是less,即降序,要注明为greater,为升序
	//vector<priority_queue ...... >
        //priority_queue的定义:priority_queue<string,vector<string>,greater<string> >
        unordered_map<string, int>::iterator it;
        for (it = mp.begin(); it != mp.end();it++){
            bucket[it->second].push(it->first);
        }
        vector<string> res;
        for (int i = bucket.size()-1; i >= 0;i--){
            while(k>0 && !bucket[i].empty()){
                k--;
                res.push_back(bucket[i].top());
                bucket[i].pop();
            }
        }
        return res;
    }
};
  • priority_queue的排序机制的写法和vector的sort的排序机制的写法正好顺序相反

973. K Closest Points to Origin

Medium

111293Add to ListShare

We have a list of points on the plane.  Find the K closest points to the origin (0, 0).

(Here, the distance between two points on a plane is the Euclidean distance.)

You may return the answer in any order.  The answer is guaranteed to be unique (except for the order that it is in.)

Example 1:

Input: points = [[1,3],[-2,2]], K = 1
Output: [[-2,2]]
Explanation: 
The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.
We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]].

Example 2:

Input: points = [[3,3],[5,-1],[-2,4]], K = 2
Output: [[3,3],[-2,4]]
(The answer [[-2,4],[3,3]] would also be accepted.)

Note:

  1. 1 <= K <= points.length <= 10000
  2. -10000 < points[i][0] < 10000
  3. -10000 < points[i][1] < 10000
/*973. K Closest Points to Origin*/
#include"pch.h"
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct Node {
	int x;
	vector<int> y;
};
struct cmp_q {
	bool operator()(Node a, Node b) {
		return a.x > b.x;
	}
};
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
	priority_queue < pair<int, vector<int> >, vector<pair<int, vector<int> > >, greater<pair<int, vector<int> > > > q;
	for (int i = 0; i < points.size(); i++) {
		int sum = points[i][0] * points[i][0] + points[i][1] * points[i][1];
		q.push({ sum,{points[i][0],points[i][1]} });
	}
	vector<vector<int> > res;
	for (int i = 0; i < K; i++) {
		res.push_back(q.top().second);
		q.pop();
	}
	return res;
}
int main(){
	vector<vector<int> > points = { {1,3},{2,-2} };
	vector<vector<int> > res = kClosest(points, 1);
	for (int i = 0; i < res.size(); i++) {
		cout << res[i][0] << " " << res[i][1] << endl;
	}
	return 0;
}

1054. Distant Barcodes

Medium

21915Add to ListShare

In a warehouse, there is a row of barcodes, where the i-th barcode is barcodes[i].

Rearrange the barcodes so that no two adjacent barcodes are equal.  You may return any answer, and it is guaranteed an answer exists.

Example 1:

Input: [1,1,1,2,2,2]
Output: [2,1,2,1,2,1]

Example 2:

Input: [1,1,1,1,2,2,3,3]
Output: [1,3,1,3,2,1,2,1]

Note:

  1. 1 <= barcodes.length <= 10000
  2. 1 <= barcodes[i] <= 10000
/*973. K Closest Points to Origin*/
#include"pch.h"
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<unordered_map>
using namespace std;
//1.优先队列存放,每次先取最大的,再取次大的
//Runtime: 452 ms, faster than 6.89% of C++ online submissions for Distant Barcodes.
//Memory Usage : 45.3 MB, less than 100.00% of C++ online submissions for Distant Barcodes.
vector<int> rearrangeBarcodes1(vector<int>& barcodes) {
	unordered_map<int, int> mp;
	for (int i = 0; i < barcodes.size(); i++) mp[barcodes[i]]++;
	priority_queue<vector<int>, vector<vector<int> >, less<vector<int> > > q;
	unordered_map<int, int> ::iterator it;
	for (it = mp.begin(); it != mp.end(); it++) {
		q.push({ it->second,it->first });
	}
	vector<int> res;
	while (!q.empty()) {
		vector<int> tmp = q.top();
		q.pop();
		res.push_back(tmp[1]);
		tmp[0] -= 1;
		if (!q.empty()) {
			vector<int> tmpp = q.top();
			q.pop();
			res.push_back(tmpp[1]);
			tmpp[0] -= 1;
			if (tmpp[0] > 0) q.push({ tmpp[0],tmpp[1] });
			if (tmp[0] > 0) q.push({ tmp[0],tmp[1] });
		}
	}
	return res;
}
/*2.贪心原则,将每种数字按照出现的次数从大到小排序,然后先依次填位置 1、3、5 等奇数位置,然后再填偶数位置。
/时间复杂度:将数字的个数排序,最坏需要 O(nlogn) 的时间。
空间复杂度:需要数组额外存储数字的个数,还需要哈希表辅助记录,需要记录答案的数组,故空间复杂度为 O(n)。
Runtime: 216 ms, faster than 80.54% of C++ online submissions for Distant Barcodes.
Memory Usage: 21 MB, less than 100.00% of C++ online submissions for Distant Barcodes.*/
static bool cmp(const pair<int, int> &a, const pair<int, int> &b) {
	return a.first > b.first;
}
vector<int> rearrangeBarcodes2(vector<int>& barcodes) {
	unordered_map<int, int> mp;
	for (int i = 0; i < barcodes.size(); i++) mp[barcodes[i]]++;
	vector<pair<int, int> >sorted;
	unordered_map<int, int>::iterator it;
	for (it = mp.begin(); it != mp.end(); it++) {
		sorted.push_back({ it->second,it->first });
	}
	sort(sorted.begin(), sorted.end(), cmp);
	int k = 0;
	for (int i = 0; i < sorted.size(); i++) {
		int num = sorted[i].first;
		while (num--) {
			if (k  < barcodes.size()) {
				barcodes[k] = sorted[i].second;
				k += 2;
			}
			else {
				k = 1;
				barcodes[k] = sorted[i].second;
				k += 2;
			}
		}
	}
	return barcodes;
}
int main(){
	vector<int> barcodes = { 2,2,2,1,5 };
	vector<int> res = rearrangeBarcodes2(barcodes);
	for (int i = 0; i < res.size(); i++) {
		cout << res[i] << " ";
	}
	return 0;
}

378. Kth Smallest Element in a Sorted Matrix

Medium

1799106Add to ListShare

Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.

Note that it is the kth smallest element in the sorted order, not the kth distinct element.

Example:

matrix = [
   [ 1,  5,  9],
   [10, 11, 13],
   [12, 13, 15]
],k = 8,return 13.

Note:
You may assume k is always valid, 1 ≤ k ≤ n2.

/*973. K Closest Points to Origin*/
#include"pch.h"
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<unordered_map>
#include<set>
using namespace std;
/*找到矩阵中第k大的数字,矩阵行、列有序
matrix = [[ 1,  5,  9],
		  [10, 11, 13],
		  [12, 13, 15]],k = 8,return 13*/
		  /*1.二维变一维:
		  Runtime: 60 ms, faster than 48.36% of C++ online submissions for Kth Smallest Element in a Sorted Matrix.
		  Memory Usage: 13.4 MB, less than 31.82% of C++ online submissions for Kth Smallest Element in a Sorted Matrix.*/
int kthSmallest1(vector<vector<int>>& matrix, int k) {
	priority_queue<int> st;
	for (int i = 0; i < matrix.size(); i++) {
		for (int j = 0; j < matrix.size(); j++) {
			st.push(matrix[i][j]);
		}
	}
	k = st.size() - k;
	int tmp;
	for (int i = 0; i <= k; i++) {
		tmp = st.top();
		st.pop();
	}
	return tmp;
}
/*2.维护大小为k的最大堆:priority_queue,less,降序,数字越大优先级越高,在队首
求第k小的数,维持一个k大小的最大堆,当堆中数量==k,直接跳到下一行,因为本行的下一个一定比当前堆顶大,不必入堆
Runtime: 48 ms, faster than 67.53% of C++ online submissions for Kth Smallest Element in a Sorted Matrix.
Memory Usage: 13.1 MB, less than 40.91% of C++ online submissions for Kth Smallest Element in a Sorted Matrix.*/
int kthSmallest2(vector<vector<int>>& matrix, int k) {
	priority_queue<int> q;
	for (int i = 0; i < matrix.size(); i++) {
		if (q.size() == k && matrix[i][0] > q.top()) return q.top();
		for (int j = 0; j < matrix.size(); j++) {
			if (q.size() == k) {
				if (matrix[i][j] >= q.top()) break;
				else {
					q.pop();
					q.push(matrix[i][j]);
				}
			}
			else {
				q.push(matrix[i][j]);
			}
		}
	}
	return q.top();
}
/*3.二分查找:左上角一定最小,右下角一定最大,找出中间数字,
由于不同行之间的元素并不严格有序,所以每一行都要查找mid,
使用upper_bound(第一个大于该元素的位置)
如果目标数比该行尾元素大,那么upper_bound返回该行元素个数,
如果目标数比该行首元素小,那么upper_bound返回0,
遍历完所有的行,可以找出中间数是第几小的数,
与k比较,进行二分查找。时间复杂度:O(nlgn * lgx) , x=max-min
Runtime: 36 ms, faster than 94.89% of C++ online submissions for Kth Smallest Element in a Sorted Matrix.
Memory Usage: 12 MB, less than 100.00% of C++ online submissions for Kth Smallest Element in a Sorted Matrix.*/
int kthSmallest3(vector<vector<int>>& matrix, int k) {
	int left = matrix[0][0], right = matrix[matrix.size() - 1][matrix.size() - 1];
	while (left < right) {
		int mid = left + (right - left) / 2;
		int tmp = 0;
		for (int i = 0; i < matrix.size(); i++) {
			tmp += upper_bound(matrix[i].begin(), matrix[i].end(), mid) - matrix[i].begin();
		}
		if (tmp < k) left = mid + 1;
		else right = mid;
	}
	return left;
}
/*4.由于列之间也是有序的,所以不用对每一行都二分查找,
从左下角开始,如果比目标值小,就右移一位,反之,上移一位
如果是右移,那么右移之前那个数的上面所有数字都小于目标值,tmp+=i+1
Runtime: 36 ms, faster than 94.89% of C++ online submissions for Kth Smallest Element in a Sorted Matrix.
Memory Usage: 11.9 MB, less than 100.00% of C++ online submissions for Kth Smallest Element in a Sorted Matrix.*/
int kthSmallest4(vector<vector<int>>& matrix, int k) {
	int left = matrix[0][0], right = matrix[matrix.size() - 1][matrix.size() - 1];
	while (left < right) {
		int mid = left + (right - left) / 2;
		int tmp = 0;
		int i = matrix.size() - 1, j = 0;//行,列
		while (i >= 0 && j < matrix.size()) {
			if (matrix[i][j] > mid) i--;
			else if (matrix[i][j] <= mid) {
				tmp += i + 1;
				j++;
			}
		}
		if (tmp < k) left = mid + 1;
		else right = mid;
	}
	return left;
}
int main() {
	vector<vector<int> > matrix = { {1,5,9},{10,11,13},{12,13,15} };
	cout << kthSmallest3(matrix, 8) << endl;
	return 0;
}

373. Find K Pairs with Smallest Sums

Medium

101585Add to ListShare

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:

Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
Output: [[1,2],[1,4],[1,6]] 
Explanation: 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:

Input: nums1 = [1,1,2], nums2 = [1,2,3], k = 2
Output: [1,1],[1,1]
Explanation: 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:

Input: nums1 = [1,2], nums2 = [3], k = 3
Output: [1,3],[2,3]
Explanation: All possible pairs are returned from the sequence: [1,3],[2,3]
/*373. Find K Pairs with Smallest Sums*/
#include"pch.h"
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<unordered_map>
#include<set>
using namespace std;
struct cmp_q {
	bool operator()(const pair<int, int> &a, const pair<int, int> &b) {
		return a.first + a.second < b.first + b.second;
		//与vector的sort定义是相反的,若想要实现升序(前k个最小的和),返回 >
	}
};
vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
	priority_queue<pair<int, int>, vector<pair<int, int> >, cmp_q> q;
	for (int i = 0; i < nums1.size(); i++) {
		for (int j = 0; j < nums2.size(); j++) {
			if (q.size() == k) {
				if (nums1[i] + nums2[j] < q.top().first+q.top().second) {
					q.pop();
					q.push({ nums1[i],nums2[j] });
				}
				else break;
			}
			else {
				q.push({ nums1[i],nums2[j] });
			}
		}
	}
	vector<vector<int> > res;
	while (!q.empty()) {
		res.push_back({ q.top().first,q.top().second });
		q.pop();
	}
	return res;
}
int main(){
	vector<int> nums1 = { 1,1,2 };
	vector<int> nums2 = { 1,2,3 };
	vector<vector<int> > res = kSmallestPairs(nums1, nums2,2);
	for (int i = 0; i < res.size(); i++) {
		cout << res[i][0] << " " << res[i][1] << endl;
	}
	return 0;
}

719. Find K-th Smallest Pair Distance

Hard

73625Add to ListShare

Given an integer array, return the k-th smallest distance among all the pairs. The distance of a pair (A, B) is defined as the absolute difference between A and B.

Example 1:

Input:nums = [1,3,1]k = 1
Output: 0 
Explanation:
Here are all the pairs:
(1,3) -> 2
(1,1) -> 0
(3,1) -> 2
Then the 1st smallest distance pair is (1,1), and its distance is 0.

Note:

  1. 2 <= len(nums) <= 10000.
  2. 0 <= nums[i] < 1000000.
  3. 1 <= k <= len(nums) * (len(nums) - 1) / 2.
/*719. Find K-th Smallest Pair Distance*/
#include"pch.h"
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<unordered_map>
#include<set>
using namespace std;
/*第k个小的和*/
/*1.priority_queue,超时*/
int smallestDistancePair1(vector<int>& nums, int k) {
	sort(nums.begin(), nums.end());
	priority_queue<int> q;
	for (int i = 0; i < nums.size(); i++) {
		for (int j = i + 1; j < nums.size(); j++) {
			if (q.size() == k) {
				if (nums[j] - nums[i] < q.top()) {
					q.pop();
					q.push(nums[j] - nums[i]);
				}
				else break;
			}
			else {
				q.push(nums[j] - nums[i]);
			}
		}
	}
	return q.top();
}
/*2.桶排序:0 <= nums[i] < 1000000,创建1000000个桶,桶中存储距离
Runtime: 1272 ms, faster than 5.05% of C++ online submissions for Find K-th Smallest Pair Distance.
Memory Usage: 93.1 MB, less than 8.33% of C++ online submissions for Find K-th Smallest Pair Distance.*/
int smallestDistancePair2(vector<int>& nums, int k) {
	int n = nums.size();
	vector<int> bucket(1000000, 0);
	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++) {
			bucket[abs(nums[i] - nums[j])]++;
		}
	}
	int res = 0;
	for (int i = 0; i < 1000000; i++) {
		while (k && bucket[i]) {
			k--;
			bucket[i]--;
		}
		if (k == 0) {
			res = i;
			break;
		}
	}
	return res;
}
/*3.二分,先排序,起始left=0,right=结束位置
每次start都从最小的位置0开始,从头遍历整个数组,
计算对于每个nums[i],其与前面的数字距离超过mid的个数,
如果超过mid的个数大于指定的k,说明要找的数字在左边,调整right,
反之,说明要找的数字在右边,调整left。
Runtime: 8 ms, faster than 99.39% of C++ online submissions for Find K-th Smallest Pair Distance.
Memory Usage: 9.3 MB, less than 83.33% of C++ online submissions for Find K-th Smallest Pair Distance.*/
int smallestDistancePair3(vector<int>& nums, int k) {
	sort(nums.begin(), nums.end());
	int left = 0, right = nums[nums.size()-1]-nums[0];
	while (left < right) {
		int mid = left + (right - left) / 2;
		int tmp = 0, start = 0;
		for (int i = 0; i < nums.size(); i++) {
			while (start<nums.size() && nums[i] - nums[start]>mid) start++;
			tmp += i - start;
		}
		if (tmp >= k) right = mid;
		else  left = mid + 1;
	}
	return right;
}
int main() {
	vector<int> nums = { 1,3,1 };
	cout << smallestDistancePair3(nums, 1);
	return 0;
}

658. Find K Closest Elements

Medium

979202Add to ListShare

Given a sorted array, two integers k and x, find the k closest elements to x in the array. The result should also be sorted in ascending order. If there is a tie, the smaller elements are always preferred.

Example 1:

Input: [1,2,3,4,5], k=4, x=3
Output: [1,2,3,4]

Example 2:

Input: [1,2,3,4,5], k=4, x=-1
Output: [1,2,3,4]

Note:

  1. The value k is positive and will always be smaller than the length of the sorted array.
  2. Length of the given array is positive and will not exceed 104
  3. Absolute value of elements in the array and x will not exceed 104
/*658. Find K Closest Elements*/
#include"pch.h"
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<unordered_map>
#include<set>
using namespace std;
/*1.数组中每个数与x的差值绝对值,前k小的数
使用priority_queue:
Runtime: 164 ms, faster than 15.81% of C++ online submissions for Find K Closest Elements.
Memory Usage: 15.9 MB, less than 16.67% of C++ online submissions for Find K Closest Elements.*/
vector<int> findClosestElements1(vector<int>& arr, int k, int x) {
	priority_queue<pair<int, int>,vector<pair<int,int> >,less<pair<int,int> > > q;//默认less,大的先出队
	for (int i = 0; i < arr.size(); i++) {
		if (q.size() == k) {
			if (abs(arr[i] - x) < q.top().first) {
				q.pop();
				q.push({ abs(arr[i] - x),arr[i] });
			}
			else if (arr[i] - x > 0 && abs(arr[i] - x) > q.top().first) break;
		}
		else q.push({ abs(arr[i] - x),arr[i] });
	}
	vector<int> res;
	while (!q.empty()) {
		res.push_back(q.top().second);
		q.pop();
	}
	sort(res.begin(), res.end());
	return res;
}
/*2.桶排序:k<数组长度,数组长度<=10000,-10000<=每个数的值(包括x)<=10000
Runtime: 144 ms, faster than 21.11% of C++ online submissions for Find K Closest Elements.
Memory Usage: 50.1 MB, less than 16.67% of C++ online submissions for Find K Closest Elements.*/
vector<int> findClosestElements2(vector<int>& arr, int k, int x) {
	vector<vector<int> > bucket(20001);
	for (int i = 0; i < arr.size(); i++) {
		bucket[abs(arr[i] - x)].push_back(arr[i]);
	}
	vector<int> res;
	for (int i = 0; i < 20001; i++) {
		if (bucket[i].size() != 0) {
			if (bucket[i].size() < k) {
				k -= bucket[i].size();
				for (int j = 0; j < bucket[i].size(); j++) res.push_back(bucket[i][j]);
			}
			else {
				for (int j = 0; j < k; j++) res.push_back(bucket[i][j]);
				i = 20001;
			}
		}
	}
	sort(res.begin(), res.end());
	return res;
}
/*3.二分法:找到第一个不小于x的数,然后向左右遍历
Runtime: 104 ms, faster than 56.01% of C++ online submissions for Find K Closest Elements.
Memory Usage: 13.8 MB, less than 16.67% of C++ online submissions for Find K Closest Elements.*/
vector<int> findClosestElements3(vector<int>& arr, int k, int x) {
	int tar = lower_bound(arr.begin(), arr.end(), x)-arr.begin();
	int left = tar - 1, right = tar; 
	vector<int> res;
	while (k>0 && left >= 0 && right < arr.size()) {
		if (k>0 && abs(arr[left] - x) <= abs(arr[right]- x)) {
			res.push_back(arr[left]);
			left--;
			k--;
		}
		else if (k > 0 && abs(arr[left] - x) > abs(arr[right]-x)) {
			res.push_back(arr[right]);
			right++;
			k--;
		}
	}
	while (k > 0 && left >= 0) {
		res.push_back(arr[left--]);
		k--;
	}
	while (k > 0 && right < arr.size()) {
		res.push_back(arr[right++]);
		k--;
	}
	sort(res.begin(), res.end());
	return res;
}
/*4.二分法:每次比较mid与x的距离和mid+k与x的距离,从而判断折半的方向
Runtime: 100 ms, faster than 79.15% of C++ online submissions for Find K Closest Elements.
Memory Usage: 13.1 MB, less than 66.67% of C++ online submissions for Find K Closest Elements.*/
vector<int> findClosestElements4(vector<int>& arr, int k, int x) {
	int left = 0, right = arr.size() - k;
	while (left < right) {
		int mid = left + (right - left)/2;
		if (x - arr[mid] > arr[mid + k] - x) left = mid + 1;
		else right = mid;
	}
	return vector<int>(arr.begin() + left, arr.begin() + left + k);
}
int main() {
	vector<int> nums = { 1,2,3,4,5 };
	vector<int> res = findClosestElements4(nums, 4,3);
	for (int i = 0; i < res.size(); i++) {
		cout << res[i] << " ";
	}
	return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值