vb.net中递归退到最外层_数组中的逆序对
生活随笔
收集整理的這篇文章主要介紹了
vb.net中递归退到最外层_数组中的逆序对
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
在數組中的兩個數字,如果前面一個數字大于后面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。并將P對1000000007取模的結果輸出。 即輸出P%1000000007
輸入描述:
題目保證輸入的數組中沒有的相同的數字 數據范圍: 對于%50的數據,size<=10^4 對于%75的數據,size<=10^5 對于%100的數據,size<=2*10^5示例:
輸入: {1, 2, 3, 4, 5, 6, 7, 0} 返回值: 7解題思路及代碼
方法一:暴力列舉
暴力列舉所有的數對,然后判斷是否逆序。
具體方法是:按住一個arr[i], 依次判斷{i+1 ... n-1]是否滿足條件。n為數組的大小。
代碼如下:
class Solution { private:const int kmod = 1000000007; public:int InversePairs(vector<int> data) {int ret = 0;int n = data.size();for (int i = 0; i < n; ++i) {for (int j = i + 1; j < n; ++j) {if (data[i] > data[j]) {ret += 1;ret %= kmod;}}}return ret;} };對于10^5數據,O(N^2)算法顯然超時。
時間復雜度:O(N^2)
空間復雜度:O(1)
方法二:歸并排序思想
對數組一邊進行歸并排序,一邊計算逆序對。
首先明確歸并排序的過程:
- 遞歸劃分整個區間為基本相等的左右兩個區間
- 合并兩個有序區間
歸并排序的代碼:
// 合并過程 void merge__(vector<int> &arr, int l, int mid, int r) {// 在這個地方創建額外空間,是一種不好的做法,更好的做法是:直接在最外層開辟一個足夠大的數組,然后傳引用到函數。vector<int> tmp(r - l + 1);int i = l, j = mid + 1, k = 0;while (i <= mid && j <= r) {if (arr[i] >= arr[j]) {tmp[k++] = arr[j++];}else {tmp[k++] = arr[i++];}}while (i <= mid) {tmp[k++] = arr[i++];}while (j <= r) {tmp[k++] = arr[j++];}for (k = 0, i = l; i <= r; ++i, ++k) {arr[i] = tmp[k];} }// 遞歸劃分過程 void merge_sort__(vector<int> &arr, int l, int r) {// 只有一個數字,則停止劃分if (l >= r) {return;}int mid = l + ((r - l) >> 1);merge_sort__(arr, l, mid);merge_sort__(arr, mid + 1, r);// 合并兩個有序區間merge__(arr, l, mid, r); } // 要排序的數組 arr void merge_sort(vector<int>& arr) {merge_sort__(arr, 0, arr.size() - 1); }本題中如何利用歸并排序的思想?
如果兩個區間為[4, 3] 和[1, 2]
那么逆序數為(4,1),(4,2),(3,1),(3,2),同樣的如果區間變為有序,比如[3,4] 和 [1,2]的結果是一樣的,也就是說區間有序和無序結果是一樣的。
但是如果區間有序會有什么好處嗎?
當然,如果區間有序,比如[3,4] 和 [1,2]
如果3 > 1, 顯然3后面的所有數都是大于1, 這里為 4 > 1, 明白其中的奧秘了吧。所以我們可以在合并的時候利用這個規則。
代碼如下:
class Solution { private:const int kmod = 1000000007; public:int InversePairs(vector<int> data) {int ret = 0;// 在最外層開辟數組vector<int> tmp(data.size());merge_sort__(data, tmp, 0, data.size() - 1, ret);return ret;}void merge_sort__(vector<int> &arr, vector<int> &tmp, int l, int r, int &ret) {if (l >= r) {return;}int mid = l + ((r - l) >> 1);merge_sort__(arr, tmp, l, mid, ret);merge_sort__(arr, tmp, mid + 1, r, ret);merge__(arr, tmp, l, mid, r, ret);}void merge__(vector<int> &arr, vector<int> &tmp, int l, int mid, int r, int &ret) {int i = l, j = mid + 1, k = 0;while (i <= mid && j <= r) {if (arr[i] > arr[j]) {tmp[k++] = arr[j++];// 奧妙之處ret += (mid - i + 1);ret %= kmod;}else {tmp[k++] = arr[i++];}}while (i <= mid) {tmp[k++] = arr[i++];}while (j <= r) {tmp[k++] = arr[j++];}for (k = 0, i = l; i <= r; ++i, ++k) {arr[i] = tmp[k];}}};Java 版:
private long cnt = 0; private int[] tmp; // 在這里聲明輔助數組,而不是在 merge() 遞歸函數中聲明public int InversePairs(int[] nums) {tmp = new int[nums.length];mergeSort(nums, 0, nums.length - 1);return (int) (cnt % 1000000007); }private void mergeSort(int[] nums, int l, int h) {if (h - l < 1)return;int m = l + (h - l) / 2;mergeSort(nums, l, m);mergeSort(nums, m + 1, h);merge(nums, l, m, h); }private void merge(int[] nums, int l, int m, int h) {int i = l, j = m + 1, k = l;while (i <= m || j <= h) {if (i > m)tmp[k] = nums[j++];else if (j > h)tmp[k] = nums[i++];else if (nums[i] <= nums[j])tmp[k] = nums[i++];else {tmp[k] = nums[j++];this.cnt += m - i + 1; // nums[i] > nums[j],說明 nums[i...mid] 都大于 nums[j]}k++;}for (k = l; k <= h; k++)nums[k] = tmp[k]; }時間復雜度:O(NlogN)
空間復雜度:O(N)
解析參考來自:
數組中的逆序對_牛客網?www.nowcoder.com總結
以上是生活随笔為你收集整理的vb.net中递归退到最外层_数组中的逆序对的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: django orm mysql_Dja
- 下一篇: java网络篇-tcp的握手和挥手!