腾讯2020校园招聘----逆序对
生活随笔
收集整理的這篇文章主要介紹了
腾讯2020校园招聘----逆序对
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
騰訊2020校園招聘----逆序對
文章目錄
- 騰訊2020校園招聘----逆序對
- 一、題目描述
- 二、題目分析
- 方法一:暴力求解(超時)
- 方法二:優化
一、題目描述
二、題目分析
首先,我們看到要求逆序對,我們做出這道題的前提是會求逆序對,所以先分析怎么求逆序對;
答案:《劍指offer》36題
代碼:
class Solution { public://簡單的歸并排序//最好在過程當中%一下,否則不過long long Merge(vector<int>& data,int begin,int end,vector<int>& temp){if(begin == end){return 0;}long long count = 0;int mid = (begin + end) >> 1;//把數組分為更小的左右兩部分int left = Merge(data,begin,mid,temp)% 1000000007;int right = Merge(data,mid + 1,end,temp)% 1000000007;//進行標記int begin1 = begin;int end1 = mid;int begin2 = mid + 1;int end2 = end;int index = end;//每一塊比較大小while(begin1 <= end1 && begin2 <= end2){//如果前面區間的數字比后面區間的數字大,就構成逆序對//逆序對的個數為后面區間的begin到end(end是在動態改變的)位置處的元素的個數//原因是歸并的特性,是先把小區間有序,在合并大區間有序,所以兩個區間內部肯定是有序的//如果前面區間的某個數字m比后面區間的某個數字n大,那么m就比后面區間的某個//數字m之前的數都大if(data[end1] > data[end2]){count = (count + end2 - begin2 + 1)% 1000000007;temp[index] = data[end1];end1--;index--;}else {temp[index] = data[end2];end2--;index--;}}while(end1 >= begin1){temp[index--] = data[end1--];}while(end2 >= begin2){temp[index--] = data[end2--];}//拷貝for(int i = begin;i <= end ;i++){data[i] = temp[i]; }//左邊區間的逆序對的個數 + 由邊區間的逆序對的個數 + 合并兩個區間的逆序對的個數return (left + right + count)% 1000000007;}int InversePairs(vector<int> data) {if(data.empty()){return 0;}vector<int> temp(data.size());return Merge(data,0,data.size() - 1,temp) ;} };方法一:暴力求解(超時)
你會求逆序對,剩下就是反轉了,直接看代碼:
#include <iostream> #include <vector> #include <algorithm> #include <stack> using namespace std;long long Merge(vector<int> info,int begin,int end,vector<int> temp) {if(begin == end){return 0;}long long count = 0;int mid = (begin + end) >> 1;long long left = Merge(info,begin,mid,temp);long long right = Merge(info,mid + 1,end,temp);int begin1 = begin;int end1 = mid;int begin2 = mid + 1;int end2 = end;int index = end;while(begin1 <= end1 && begin2 <= end2){if(info[end1] > info[end2]){count = count + end2 - begin2 + 1;temp[index--] = info[end1--];}else{temp[index--] = info[end2--];}}while(end1 >= begin1){temp[index--] = info[end1--];}while(end2 >= begin2){temp[index--] = info[end2--];}//拷貝for(int i = begin;i <= end ;i++){info[i] = temp[i];}//左邊區間的逆序對的個數 + 由邊區間的逆序對的個數 + 合并兩個區間的逆序對的個數return (left + right + count); }void InversePairs(vector<int> info) {vector<int> temp(info.size());cout<<Merge(info,0,info.size() - 1,temp)<<endl; }void Reverse(vector<int>& info,int num) {int count = info.size() / num;for(int i = 0;i < count;i++){reverse((info.begin() + i * num),info.begin() + ((i + 1) * num));}InversePairs(info); }void GetReverseCount(vector<int>& info,vector<int>& ans) {for(auto e : ans){int num = pow(2,e);Reverse(info,num);} }int main() {int n;cin>>n;vector<int> v(pow(2,n));for(int i = 0;i < pow(2,n);i++){cin>>v[i];}int num;cin>>num;vector<int> ans(num);for(int i = 0;i < num;i++){cin>>ans[i];}GetReverseCount(v,ans);return 0; }方法二:優化
每次翻轉,然后利用歸并排序求解逆序對,復雜度太高,只能通過50%的數據。顯然每次都要歸并排序成本太高,那么可不可只使用一次歸并排序哪?
- 可以發現,逆序對翻轉后,變成順序對,如1 2,翻轉變成2 1。
- 因此我們需要 記錄不同長度的逆序對和順序對的數量,當翻轉時,僅需交換小于等于該翻轉長度的逆序對和順序對(因為大于翻轉長度的逆序對不會收到影響),將所有的逆序對加起來即可得到結果。
- 舉個例子,如 2 1 4 3,長度為2 ^ 1的逆序對數量為2(2 1一對,4 3一對),長度為2 ^ 2的逆序對數量為0(2 1 4 3中2 1 和4 3不構成逆序對,不要重復計算)。之后便可以只交換逆序對和順序對數量,求逆序對的和即可。
- 順序對怎么計算,可以考慮用 總數-逆序對-相等的對
總結
以上是生活随笔為你收集整理的腾讯2020校园招聘----逆序对的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 腾讯2020校园招聘---假期
- 下一篇: shell编程之条件判断语句和流程控制语