日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

腾讯2020校园招聘----逆序对

發布時間:2024/4/11 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 腾讯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不構成逆序對,不要重復計算)。之后便可以只交換逆序對和順序對數量,求逆序對的和即可。
  • 順序對怎么計算,可以考慮用 總數-逆序對-相等的對
#include <vector> #include <iostream> #include <math.h> using namespace std; void merge(vector<long long int>&nums, long long int lbegin, long long int lend,long long int rbegin,long long int rend,long long int index,vector<long long int>&cnt) {long long int p1 = lbegin, p2 = rbegin;vector<long long int> tmp(rend - lbegin + 1);long long int i = 0;long long int pairsCnt = 0;while (p1 <= lend && p2 <= rend) {if (nums[p1] <= nums[p2]) {tmp[i++] = nums[p1++];}else if(nums[p1]>nums[p2]){pairsCnt += (lend - p1 + 1);tmp[i++] = nums[p2++];}}while (p1 <= lend) {tmp[i++] = nums[p1++];}while (p2 <= rend) {tmp[i++] = nums[p2++];}for (int i = 0; i < tmp.size(); i++) {nums[lbegin++] = tmp[i];}cnt[index] += pairsCnt; } void mergeSort(vector<long long int>& nums, long long int begin, long long int end, long long int index,vector<long long int>& cnt) {if (begin == end)return;long long int mid = (end - begin) / 2 + begin;mergeSort(nums, begin, mid,index-1,cnt);mergeSort(nums, mid + 1, end,index-1,cnt);merge(nums, begin, mid, mid + 1, end,index,cnt); } int main() {ios::sync_with_stdio(false);long long int n;cin >> n;long long int cnt = pow(2, n);vector<long long int> nums;while (cnt--) {long long int tmp;cin >> tmp;nums.push_back(tmp);}vector<long long int> order(n+1,0);//保存不同長度的順序對個數vector<long long int> reOrder(n+1,0);//保存不同長度的逆序對個數vector<long long int> reverse_nums(nums.rbegin(), nums.rend());mergeSort(nums, 0, nums.size() - 1,n,reOrder);mergeSort(reverse_nums, 0, reverse_nums.size() - 1, n,order);long long int m;cin >> m;while (m--) {long long int q;cin >> q;long long int cnt = 0;for (long long int i = 1; i <= q; i++) {swap(order[i], reOrder[i]);//每次反轉后,需要交換q范圍內順序對和逆序對的數量}for (long long int i = 1; i <= n; i++) {cnt += reOrder[i];}cout << cnt << endl;}system("pause");return 0; }

總結

以上是生活随笔為你收集整理的腾讯2020校园招聘----逆序对的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。