- 折半查找27的过程;
- 快速排序的思路和第一趟结果;
答:快速排序(Quick Sort)是一种高效的排序算法,其基本思路是采用分治策略来处理排序问题。快速排序的主要步骤如下:
选取一个基准值(pivot):从序列中选择一个元素作为基准值。基准值的选取方法有多种,例如可以选择序列的第一个元素、最后一个元素或者随机选择一个元素。
分区(partition):将序列中的其他元素与基准值进行比较,将小于基准值的元素放在基准值的左侧,大于基准值的元素放在基准值的右侧。这个过程完成后,基准值会被放置到正确的位置,即基准值左侧的所有元素都小于基准值,右侧的所有元素都大于基准值。
递归处理子序列:对基准值左侧和右侧的两个子序列分别进行快速排序。这个过程会递归地将子序列划分为更小的子序列,并对这些子序列进行排序。递归结束的条件是序列中只剩下一个元素或没有元素。
合并子序列:由于基准值的左侧和右侧子序列都是有序的,所以整个序列也是有序的。在快速排序过程中,合并子序列的操作实际上是隐式完成的,因为在每次递归调用中,基准值都会被放置到正确的位置。
通过以上步骤,快速排序能够将序列排列成有序状态。快速排序的平均时间复杂度为 O(n*log(n)),在实际应用中具有较好的性能。然而,在最坏情况下(序列已经有序或逆序),快速排序的时间复杂度退化为 O(n^2)。为避免这种情况,可以通过随机选取基准值或使用其他改进方法来优化算法性能。
- 图的邻接表数据结构;
算法题:
1.回文串,示例为level;
回文串是指一个字符串从前往后读和从后往前读都是相同的。在 C++ 中,可以通过比较字符串的对称位置的字符来判断一个字符串是否为回文串。下面是一个简单的示例代码:
#include <iostream>
#include <string>
bool isPalindrome(const std::string &str) {
int left = 0;
int right = str.size() - 1;
while (left < right) {
if (str[left] != str[right]) {
return false;
}
left++;
right--;
}
return true;
}
int main() {
std::string input = "level";
if (isPalindrome(input)) {
std::cout << input << " 是回文串。" << std::endl;
} else {
std::cout << input << " 不是回文串。" << std::endl;
}
return 0;
}
在这个示例中,我们定义了一个名为 isPalindrome 的函数,用于判断输入字符串是否为回文串。然后,我们使用 "level" 作为输入字符串,调用 isPalindrome 函数并输出结果。如果你想要测试其他字符串,只需将 input 变量的值更改为其他字符串即可。
2.查找链表倒数第k个元素;
为了在链表中查找倒数第 k 个元素,可以使用双指针法。首先让一个指针 fast 先向前移动 k 个位置,然后让第二个指针 slow 从链表头开始。接下来,同时移动两个指针,直到 fast 指针到达链表尾部。此时,slow 指针所在的位置就是倒数第 k 个元素。
以下是一个 C++ 示例代码,实现了查找链表中倒数第 k 个元素的功能:
#include <iostream>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
ListNode* findKthToLast(ListNode* head, int k) {
ListNode *fast = head;
ListNode *slow = head;
for (int i = 0; i < k; ++i) {
if (fast == nullptr) {
return nullptr; // 链表长度小于k
}
fast = fast->next;
}
while (fast != nullptr) {
fast = fast->next;
slow = slow->next;
}
return slow;
}
int main() {
// 构建一个简单的链表: 1 -> 2 -> 3 -> 4 -> 5
ListNode *head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(3);
head->next->next->next = new ListNode(4);
head->next->next->next->next = new ListNode(5);
int k = 2;
ListNode *result = findKthToLast(head, k);
if (result != nullptr) {
std::cout << "链表倒数第 " << k << " 个元素的值为: " << result->val << std::endl;
} else {
std::cout << "链表长度小于 " << k << std::endl;
}
// 释放链表内存
while (head != nullptr) {
ListNode *temp = head;
head = head->next;
delete temp;
}
return 0;
}
这个示例中,我们首先定义了一个链表节点结构体 ListNode,然后实现了 findKthToLast 函数来查找链表中倒数第 k 个元素。在 main 函数中,我们创建了一个简单的链表,并调用 findKthToLast 函数来查找倒数第 k 个元素。最后,我们释放了链表所占用的内存。
3.判断是否为平衡二叉树;
平衡二叉树(Balanced Binary Tree)是指任意节点的左右子树的高度差不超过 1。为了判断一棵二叉树是否是平衡二叉树,我们可以自底向上地计算每个节点的左右子树高度,然后判断它们的高度差是否满足平衡条件。
以下是一个 C++ 示例代码,实现了判断二叉树是否为平衡二叉树的功能:
#include <iostream>
#include <algorithm>
#include <cmath>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
int height(TreeNode *root) {
if (root == nullptr) {
return 0;
}
int leftHeight = height(root->left);
int rightHeight = height(root->right);
if (leftHeight == -1 || rightHeight == -1 || std::abs(leftHeight - rightHeight) > 1) {
return -1;
}
return std::max(leftHeight, rightHeight) + 1;
}
bool isBalanced(TreeNode *root) {
return height(root) != -1;
}
int main() {
// 构建一个平衡二叉树:
// 3
// / \
// 9 20
// / \
// 15 7
TreeNode *root = new TreeNode(3);
root->left = new TreeNode(9);
root->right = new TreeNode(20);
root->right->left = new TreeNode(15);
root->right->right = new TreeNode(7);
if (isBalanced(root)) {
std::cout << "该二叉树是平衡二叉树。" << std::endl;
} else {
std::cout << "该二叉树不是平衡二叉树。" << std::endl;
}
// 释放二叉树内存(此处省略)
return 0;
}
在这个示例中,我们首先定义了一个二叉树节点结构体 TreeNode,然后实现了 height 函数来计算二叉树节点的高度,以及 isBalanced 函数来判断二叉树是否为平衡二叉树。在 main 函数中,我们创建了一个简单的平衡二叉树,并调用 isBalanced 函数来判断它是否为平衡二叉树。
请注意,为了简化示例,我们没有实现释放二叉树所占用内存的代码。在实际应用中,你需要确保在使用完二叉树后正确地释放内存。
4.找m*n矩阵的靶点;
在一个 m * n 的矩阵中,靶点(Saddle Point)是指一个元素在所在行是最小值,在所在列是最大值。为了找到矩阵的靶点,可以先找出每一行的最小值和每一列的最大值,然后检查这些值中是否有元素满足靶点的条件。
以下是一个 C++ 示例代码,实现了在一个 m * n 的矩阵中查找靶点的功能:
#include <iostream>
#include <vector>
std::vector<int> findSaddlePoints(const std::vector<std::vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
std::vector<int> minRow(m, INT_MAX);
std::vector<int> maxCol(n, INT_MIN);
// 找出每一行的最小值
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
minRow[i] = std::min(minRow[i], matrix[i][j]);
}
}
// 找出每一列的最大值
for (int j = 0; j < n; ++j) {
for (int i = 0; i < m; ++i) {
maxCol[j] = std::max(maxCol[j], matrix[i][j]);
}
}
// 查找靶点
std::vector<int> saddlePoints;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (matrix[i][j] == minRow[i] && matrix[i][j] == maxCol[j]) {
saddlePoints.push_back(matrix[i][j]);
}
}
}
return saddlePoints;
}
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
std::vector<int> saddlePoints = findSaddlePoints(matrix);
if (!saddlePoints.empty()) {
std::cout << "矩阵中的靶点有: ";
for (int point : saddlePoints) {
std::cout << point << " ";
}
std::cout << std::endl;
} else {
std::cout << "矩阵中没有靶点。" << std::endl;
}
return 0;
}
在这个示例中,我们定义了一个名为 findSaddlePoints 的函数,用于在一个矩阵中查找靶点。在 main 函数中,我们创建了一个简单的 m * n 矩阵,并调用 findSaddlePoints 函数来查找矩阵中的靶点。
请注意,这个示例仅适用于整数矩阵。如果你需要处理浮点数矩阵,可以将 int 类型替换为 float 或 double 类型,并在比较浮点数时考虑精度误差。
5.层序遍历二叉树和查看叶子节点个数;
#include <iostream>
#include <queue>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
void levelOrderTraversal(TreeNode *root) {
if (root == nullptr) {
return;
}
std::queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode *current = q.front();
q.pop();
std::cout << current->val << " ";
if (current->left) {
q.push(current->left);
}
if (current->right) {
q.push(current->right);
}
}
}
int countLeafNodes(TreeNode *root) {
if (root == nullptr) {
return 0;
}
if (root->left == nullptr && root->right == nullptr) {
return 1;
}
return countLeafNodes(root->left) + countLeafNodes(root->right);
}
int main() {
// 构建一个简单的二叉树:
// 1
// / \
// 2 3
// / \
// 4 5
TreeNode *root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
std::cout << "二叉树的层序遍历结果: ";
levelOrderTraversal(root);
std::cout << std::endl;
int leafNodeCount = countLeafNodes(root);
std::cout << "二叉树的叶子节点个数: " << leafNodeCount << std::endl;
// 释放二叉树内存(此处省略)
return 0;
}
在这个示例中,我们首先定义了一个二叉树节点结构体 TreeNode,然后实现了 levelOrderTraversal 函数来进行二叉树的层序遍历,以及 countLeafNodes 函数来计算叶子节点个数。在 main 函数中,我们创建了一个简单的二叉树,并调用这两个函数来输出层序遍历结果和叶子节点个数。
请注意,为了简化示例,我们没有实现释放二叉树所占用内存的代码。在实际应用中,你需要确保在使用完二叉树后正确地释放内存。
6.排列组合,例如输入1-n,输出为123,132,213,231,321,312.
#include <iostream>
#include <vector>
#include <string>
void backtrack(std::vector<std::string> &result, std::string ¤t, int n, std::vector<bool> &used) {
if (current.size() == n) {
result.push_back(current);
return;
}
for (int i = 1; i <= n; ++i) {
if (used[i - 1]) {
continue;
}
current.push_back(i + '0');
used[i - 1] = true;
backtrack(result, current, n, used);
used[i - 1] = false;
current.pop_back();
}
}
std::vector<std::string> generatePermutations(int n) {
std::vector<std::string> result;
std::string current;
std::vector<bool> used(n, false);
backtrack(result, current, n, used);
return result;
}
int main() {
int n = 3;
std::vector<std::string> permutations = generatePermutations(n);
std::cout << "n = " << n << " 的排列组合有:" << std::endl;
for (const auto &permutation : permutations) {
std::cout << permutation << std::endl;
}
return 0;
}
在这个示例中,我们定义了一个名为 backtrack 的回溯函数来生成所有排列组合。generatePermutations 函数是主要的接口函数,用于根据输入 n 生成所有排列组合。在 main 函数中,我们调用 generatePermutations 函数来输出所有排列组合。
这个示例中,n 是一个整数。你可以根据需要调整 n 的值来生成相应的排列组合。