堆数据结构基础概念、插入删除及建堆操作详解,配合 C++ 代码实现最大堆与堆排序。涵盖常见字符串处理算法,包括字母异位词判断、字符串两半相似性检测、末尾单词长度计算及回文串验证。利用双指针与哈希计数技巧优化时间复杂度,辅以堆相关选择题解析,掌握核心算法逻辑与面试考点。
Elasticer12 浏览
堆数据结构与字符串处理算法详解
一、堆数据结构基础
堆(Heap)是一种特殊的完全二叉树,根据性质可分为最大堆和最小堆。最大堆中每个节点的值都大于或等于其子节点,最小堆则相反。通常使用数组实现,对于索引为 i 的元素:
左子节点位置:2*i + 1
右子节点位置:2*i + 2
父节点位置:(i-1)/2
堆的基本操作
核心操作包括插入元素(上浮)、删除堆顶(下沉)以及建堆。
#include<vector>#include<iostream>classMaxHeap {
private:
std::vector<int> heap;
// 上浮操作voidheapifyUp(int index){
int parent = (index - 1) / 2;
if (index > 0 && heap[index] > heap[parent]) {
std::swap(heap[index], heap[parent]);
heapifyUp(parent);
}
}
// 下沉操作voidheapifyDown(int index){
int largest = index;
int left = 2 * index + 1;
int right = 2 * index + 2;
int size = heap.size();
if (left < size && heap[left] > heap[largest]) {
largest = left;
}
if (right < size && heap[right] > heap[largest]) {
largest = right;
}
(largest != index) {
std::(heap[index], heap[largest]);
(largest);
}
}
:
{
heap.(value);
(heap.() - );
}
{
(heap.()) {
std::();
}
max = heap[];
heap[] = heap.();
heap.();
(!heap.()) {
();
}
max;
}
{
heap = array;
( i = heap.() / - ; i >= ; i--) {
(i);
}
}
{
( value : heap) {
std::cout << value << ;
}
std::cout << std::endl;
}
{ heap.(); }
{ heap.(); }
};
if
swap
heapifyDown
public
// 插入元素
voidinsert(int value)
push_back
heapifyUp
size
1
// 删除堆顶元素
intextractMax()
if
empty
throw
out_of_range
"Heap is empty"
int
0
0
back
pop_back
if
empty
heapifyDown
0
return
// 建堆
voidbuildHeap(const std::vector<int>& array)
for
int
size
2
1
0
heapifyDown
// 打印堆
voidprintHeap()
for
int
" "
intsize()
return
size
boolempty()
return
empty
堆排序
堆排序利用堆的性质进行排序,主要步骤是构建最大堆,然后反复将堆顶元素移至末尾并调整堆结构。
voidheapSort(std::vector<int>& arr){
int n = arr.size();
// 构建最大堆for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// 一个个从堆顶取出元素for (int i = n - 1; i > 0; i--) {
std::swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
voidheapify(std::vector<int>& arr, int n, int i){
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
if (right < n && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
std::swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
堆排序时间复杂度为 O(nlogn),空间复杂度为 O(1)。
二、字符串处理算法
1. 有效的字母异位词
判断两个字符串是否包含相同的字符且频率一致。
classSolution {
public:
boolisAnagram(string s, string t){
if (s.length() != t.length()) {
returnfalse;
}
std::vector<int> char_counts(26, 0);
for (int i = 0; i < s.length(); ++i) {
char_counts[s[i] - 'a']++;
char_counts[t[i] - 'a']--;
}
for (auto count : char_counts) {
if (count != 0) {
returnfalse;
}
}
returntrue;
}
};
思路很简单,用数组统计字符频次差值。遍历完如果全为 0,说明互为异位词。时间复杂度 O(n)。
2. 判断字符串的两半是否相似
给定偶数长度字符串,比较前后两半元音字母数量是否相同。
classSolution {
public:
boolisVowel(char c){
c = tolower(c);
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
boolhalvesAreAlike(string s){
int begin = 0;
int count1 = 0;
int end = s.size() / 2;
int count2 = 0;
while (end < s.size()) {
if (isVowel(s[begin])) count1++;
if (isVowel(s[end])) count2++;
begin++; end++;
}
return count1 == count2;
}
};
classSolution {
public:
boolisPalindrome(string s){
int begin = 0;
int end = s.size() - 1;
while (begin < end) {
while (begin < end && !isalnum(s[begin])) begin++;
while (begin < end && !isalnum(s[end])) end--;
if (tolower(s[begin]) != tolower(s[end])) {
returnfalse;
}
begin++; end--;
}
returntrue;
}
};
双指针向中间靠拢,跳过非有效字符后比较。注意 tolower 转换。
三、堆相关选择题解析
1. 下列哪个关键码序列是一个堆?
A. 94,31,53,23,16,72
B. 94,53,31,72,16,23
C. 16,53,23,94,31,72
D. 16,31,23,94,53,72