做百度推廣網(wǎng)站排名愛站網(wǎng)是什么
1 算法題 :使用分塊算法在有序數(shù)組中查找指定元素
1.1 題目含義
在給定一個有序數(shù)組的情況下,使用分塊查找算法來查找數(shù)組中是否包含指定的元素。分塊查找算法是一種結(jié)合了順序查找和二分查找思想的算法,它將有序數(shù)組劃分為若干個塊,每個塊內(nèi)的元素不必有序,但塊與塊之間必須保持有序。首先通過塊之間的有序性來快速定位到目標(biāo)元素可能存在的塊,然后在該塊內(nèi)進(jìn)行順序查找。
1.2 示例
示例 1:
輸入:
- 有序數(shù)組:[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]
- 塊大小:5
- 目標(biāo)元素:17
輸出:
- 7
說明:
- 數(shù)組被劃分為 3 個塊:[1, 3, 5, 7, 9]、[11, 13, 15, 17, 19] 和 [21, 23, 25, 27, 29]。通過比較塊的首個元素,可以確定目標(biāo)元素 17 在第二個塊中。然后在該塊內(nèi)進(jìn)行順序查找,找到元素 17 的位置為 7(從 0 開始計數(shù))。
示例 2:
輸入:
- 有序數(shù)組:[1, 4, 6, 9, 13, 16, 19, 22, 25, 28]
- 塊大小:4
- 目標(biāo)元素:10
輸出:
- -1
說明:
- 數(shù)組被劃分為 3 個塊:[1, 4, 6, 9]、[13, 16, 19, 22] 和 [25, 28]。通過比較塊的首個元素,可以確定目標(biāo)元素 10 不在任何一個塊中,因此整個數(shù)組中也不存在該元素。
示例 3:
輸入:
- 有序數(shù)組:[]
- 塊大小:10
- 目標(biāo)元素:50
輸出:
- -1
說明:
- 有序數(shù)組為空,50 不存在于有序數(shù)組中,返回 -1。
2 解題思路
2.1 簡單分塊查找
(1)確定塊數(shù):
首先,根據(jù)給定的塊大小,計算數(shù)組可以分成的塊數(shù)。如果數(shù)組長度不是塊大小的整數(shù)倍,則最后一個塊的大小可能會小于塊大小。
(2)定位目標(biāo)塊:
遍歷數(shù)組中的塊,通過比較每個塊的首個元素和目標(biāo)元素的大小關(guān)系,確定目標(biāo)元素可能所在的塊。如果目標(biāo)元素小于當(dāng)前塊的首個元素,則目標(biāo)元素不可能在當(dāng)前塊及之后的塊中,可以提前結(jié)束遍歷。
(3)塊內(nèi)順序查找:
在定位到的目標(biāo)塊內(nèi),使用順序查找算法來查找目標(biāo)元素。從目標(biāo)塊的起始位置開始,逐個比較元素直到找到目標(biāo)元素或遍歷完整個塊。
(4)返回結(jié)果:
如果找到了目標(biāo)元素,則返回其在數(shù)組中的位置(索引)。如果遍歷完所有塊都沒有找到目標(biāo)元素,則返回表示未找到的標(biāo)志(如-1)。
2.2 優(yōu)化塊內(nèi)查找
這種思路在第一種的基礎(chǔ)上,對塊內(nèi)查找進(jìn)行了優(yōu)化。
(1)確定塊數(shù)和索引映射:
首先,像第一種思路一樣確定塊數(shù)。然后,可以建立一個索引映射關(guān)系,將每個元素映射到其所屬的塊和塊內(nèi)的相對位置。這樣可以在定位到目標(biāo)塊后,直接計算出目標(biāo)元素在塊內(nèi)的相對位置,減少不必要的比較操作。
(2)定位目標(biāo)塊:
這一步與第一種思路相同,通過比較塊的首個元素和目標(biāo)元素的大小關(guān)系,確定目標(biāo)元素可能所在的塊。
(3)塊內(nèi)直接定位:
利用索引映射關(guān)系,直接計算出目標(biāo)元素在塊內(nèi)的相對位置。然后,通過該相對位置訪問數(shù)組元素,檢查是否為目標(biāo)元素。
(4)返回結(jié)果:
如果找到了目標(biāo)元素,則返回其在數(shù)組中的位置(索引)。如果遍歷完所有塊都沒有找到目標(biāo)元素,則返回表示未找到的標(biāo)志(如-1)。
3 算法實現(xiàn)代碼
3.1 簡單分塊查找
如下為算法實現(xiàn)代碼:
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm> class Solution
{
public:// 分塊查找算法實現(xiàn) int blockSearch(const std::vector<int>& arr, int blockSize, int target) {int n = arr.size();int blockNum = (n + blockSize - 1) / blockSize; // 計算塊數(shù),向上取整 // 遍歷塊,定位目標(biāo)元素可能所在的塊 for (int i = 0; i < blockNum; ++i) {int blockStart = i * blockSize;int blockEnd = std::min(blockStart + blockSize, n); // 塊內(nèi)最后一個元素的索引 // 如果目標(biāo)元素小于當(dāng)前塊的最小值,則目標(biāo)元素不可能在當(dāng)前塊及之后的塊中 if (target < arr[blockStart]) {break;}// 如果目標(biāo)元素大于當(dāng)前塊的最大值,則繼續(xù)查找下一個塊 if (target > arr[blockEnd - 1]) {continue;}// 在目標(biāo)塊內(nèi)進(jìn)行順序查找 for (int j = blockStart; j < blockEnd; ++j) {if (arr[j] == target) {return j; // 返回目標(biāo)元素在數(shù)組中的位置 }}}return -1; // 未找到目標(biāo)元素 }
};
這段代碼首先計算了塊數(shù) blockNum,然后遍歷每個塊,通過比較塊的首個元素 arr[blockStart] 和最后一個元素 arr[blockEnd - 1] 與目標(biāo)元素 target 的大小關(guān)系,來確定目標(biāo)元素可能所在的塊。如果目標(biāo)元素小于當(dāng)前塊的最小值,則它不可能在當(dāng)前塊及之后的塊中,可以提前結(jié)束遍歷。如果目標(biāo)元素在當(dāng)前塊內(nèi),則在該塊內(nèi)進(jìn)行順序查找,直到找到目標(biāo)元素或遍歷完整個塊。如果遍歷完所有塊都沒有找到目標(biāo)元素,則返回 -1 表示未找到。
調(diào)用上面的算法,并得到輸出:
int main()
{Solution s;std::vector<int> arr = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29 };int blockSize = 5; // 塊大小 int target = 17; // 目標(biāo)元素 int index = s.blockSearch(arr, blockSize, target);if (index != -1) {std::cout << "Element found at index: " << index << std::endl;}else {std::cout << "Element not found in the array." << std::endl;}return 0;
}
上面代碼的輸出為:
Element found at index: 8
3.2 優(yōu)化塊內(nèi)查找
如下為算法實現(xiàn)代碼:
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <unordered_map> class Solution
{
public:// 分塊查找算法實現(xiàn) int blockSearch(const std::vector<int>& arr, int blockSize, int target) {int n = arr.size();int blockNum = (n + blockSize - 1) / blockSize; // 計算塊數(shù),向上取整 std::unordered_map<int, std::pair<int, int>> blockIndicesAndOffsets; // 存儲塊索引和塊內(nèi)偏移量 computeBlockIndicesAndOffsets(arr, blockSize, blockIndicesAndOffsets);// 遍歷塊,定位目標(biāo)元素可能所在的塊 for (int i = 0; i < blockNum; ++i) {int blockStart = i * blockSize;int blockEnd = std::min(blockStart + blockSize, n); // 塊內(nèi)最后一個元素的索引 // 如果目標(biāo)元素小于當(dāng)前塊的最小值,則目標(biāo)元素不可能在當(dāng)前塊及之后的塊中 if (target < arr[blockStart]) {break;}// 如果目標(biāo)元素大于當(dāng)前塊的最大值,則繼續(xù)查找下一個塊 if (target > arr[blockEnd - 1]) {continue;}// 檢查目標(biāo)元素是否在塊內(nèi),并返回其位置 auto it = blockIndicesAndOffsets.find(target);if (it != blockIndicesAndOffsets.end() && it->second.first == i) {return blockStart + it->second.second; // 返回目標(biāo)元素在數(shù)組中的位置 }}return -1; // 未找到目標(biāo)元素 }private:// 計算并存儲每個元素的塊索引和塊內(nèi)偏移量 void computeBlockIndicesAndOffsets(const std::vector<int>& arr, int blockSize,std::unordered_map<int, std::pair<int, int>>& blockIndicesAndOffsets) {int n = arr.size();for (int i = 0; i < n; ++i) {int blockIndex = i / blockSize;int offset = i % blockSize;blockIndicesAndOffsets[arr[i]] = { blockIndex, offset };}}
};
在這個代碼中,computeBlockIndicesAndOffsets 函數(shù)用于計算并存儲每個元素的塊索引和塊內(nèi)偏移量。optimizedBlockSearch 函數(shù)首先通過遍歷塊來定位目標(biāo)元素可能所在的塊,然后直接檢查目標(biāo)元素是否在預(yù)計算的塊索引和偏移量映射中,并且其塊索引與當(dāng)前遍歷的塊索引相匹配。如果找到匹配項,則直接返回目標(biāo)元素在數(shù)組中的位置。
注意:這種方法只適用于數(shù)組不會改變的情況,因為一旦數(shù)組發(fā)生變化,就需要重新計算塊索引和偏移量。此外,如果數(shù)組非常大或者元素非常多,存儲塊索引和偏移量映射可能會消耗大量內(nèi)存。因此,在實際應(yīng)用中,需要根據(jù)具體情況權(quán)衡這種優(yōu)化方法的利弊。
4 測試用例
以下是針對上面算法的測試用例,基本覆蓋了各種情況:
(1)基礎(chǔ)測試用例
輸入:數(shù)組 arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29},塊大小 blockSize = 5,目標(biāo)元素 target = 17
輸出:找到目標(biāo)元素 17,位置為 8
說明:目標(biāo)元素位于第三個塊內(nèi),算法能夠正確找到其位置。
(2)邊界測試用例
輸入:數(shù)組 arr = {1, 3, 5, 7, 9},塊大小 blockSize = 3,目標(biāo)元素 target = 1
輸出:找到目標(biāo)元素 1,位置為 0
說明:目標(biāo)元素位于數(shù)組的第一個元素,算法能夠正確處理邊界情況。
輸入:數(shù)組 arr = {1, 3, 5, 7, 9},塊大小 blockSize = 3,目標(biāo)元素 target = 9
輸出:找到目標(biāo)元素 9,位置為 4
說明:目標(biāo)元素位于數(shù)組的最后一個元素,算法能夠正確處理邊界情況。
(3)塊內(nèi)查找測試用例
輸入:數(shù)組 arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29},塊大小 blockSize = 5,目標(biāo)元素 target = 23
輸出:找到目標(biāo)元素 23,位置為 12
說明:目標(biāo)元素位于第三個塊內(nèi),但不是塊的首個或末尾元素,算法能夠在塊內(nèi)正確找到目標(biāo)元素。
(4)未找到目標(biāo)元素測試用例
輸入:數(shù)組 arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29},塊大小 blockSize = 5,目標(biāo)元素 target = 30
輸出:未找到目標(biāo)元素 30
說明:目標(biāo)元素不在數(shù)組中,算法能夠正確處理未找到目標(biāo)元素的情況。
(5)空數(shù)組測試用例
輸入:數(shù)組 arr = {},塊大小 blockSize = 5,目標(biāo)元素 target = 1
輸出:未找到目標(biāo)元素 1
說明:數(shù)組為空,算法能夠正確處理空數(shù)組的情況。
(6)單個塊測試用例
輸入:數(shù)組 arr = {1, 2, 3, 4, 5},塊大小 blockSize = 5,目標(biāo)元素 target = 3
輸出:找到目標(biāo)元素 3,位置為 2
說明:整個數(shù)組只包含一個塊,算法能夠正確處理單個塊的情況。