題目描述:給定一個字元串,請你找出其中不含有重複字元的 最長子串 的長度。
解法 1: 暴力法(TLE)
直接雙重循環,挨個檢查是否為逆序對。代碼實作比較簡單:
/**
* @param {number[]} nums
* @return {number}
*/
var reversePairs = function(nums) {
let res = 0;
const length = nums.length;
for (let i = 0; i < length; ++i) {
for (let j = i + 1; j < length; ++j) {
nums[i] > nums[j] && ++res;
}
}
return res;
};
複制
時間複雜度是$O(N^2)$。在 leetcode 上會 TLE,無法通過(畢竟這是道标注「困難」的題目)。
解法 2: 歸并排序(正确解法)
這題的正确解法是要借助歸并排序的思路,在歸并的過程中,快速統計逆序對。這種解法比較難想到,但是應用歸并排序的題目真的不多,是以這題很有研究和收藏意義。
核心的解決邏輯都封裝在 findInversePairNum 函數中。它的職能就是統計數組
arr[start, end]
範圍中的逆序對,并且統計完後,
arr[start, end]
範圍中的元素會被排序(這點和歸并排序的過程一樣)。
那麼函數又是如何快速統計逆序對的呢?大體過程如下:
- 遞歸調用,拿到左子數組和右子數組的逆序對(此時,左子數組和右子數組也都排序完成了)
- 指針 i 和 j 分别指向左子數組和右子數組的最右側,此時會有 2 種情況:
-
:那麼說明arr[i] > arr[j]
大于右子數組中所有元素,逆序對增加arr[i]
,向左邊移動指針 ij - start - length
-
: 對arr[i] <= arr[j]
來說,不存在逆序對,向左邊移動指針 jarr[i]
-
- i 和 j 周遊完各自數組後,最後傳回逆序對之和即可
代碼實作如下:
// ac位址:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
// 原文位址:https://xxoo521.com/2020-03-12-reverse-pairs/
/**
* @param {number[]} nums
* @return {number}
*/
var reversePairs = function(nums) {
return findInversePairNum(nums, 0, nums.length - 1);
};
/**
* @param {number[]} arr
* @param {number} start
* @param {number} end
*/
function findInversePairNum(arr, start, end) {
if (start >= end) return 0;
const copy = new Array(end - start + 1);
const length = Math.floor((end - start) / 2); // 左數組長度
const leftNum = findInversePairNum(arr, start, start + length);
const rightNum = findInversePairNum(arr, start + length + 1, end);
let i = start + length;
let j = end;
let copyIndex = end - start;
let num = 0;
while (i >= start && j >= start + length + 1) {
if (arr[i] > arr[j]) {
num += j - start - length;
copy[copyIndex--] = arr[i--];
} else {
copy[copyIndex--] = arr[j--];
}
}
while (i >= start) {
copy[copyIndex--] = arr[i--];
}
while (j >= start + length + 1) {
copy[copyIndex--] = arr[j--];
}
for (let k = start; k <= end; ++k) {
arr[k] = copy[k - start];
}
return num + leftNum + rightNum;
}
複制
時間複雜度是$O(NlogN)$,空間複雜度是$O(N)$。如果還是覺得不好了解,可以以數組 7、5、6、4 為例,按照前面過程,手動計算一下。