【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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章