计算机算法与数据结构知识汇总及 C++ 代码实现

目录

计算机算法与数据结构知识汇总及 C++ 代码实现

一、引言

二、队列与栈

1. 先进先出队列

2. 后进先出栈

三、滑动窗口

滑动窗口最大值问题

四、数组查找

有序数组的二分查找

五、动态规划

查找最长递增子序列

六、排序与统计

数组中逆序对统计

七、集合操作

1. 快速获取集合重复值

2. 快速获取集合最值

八、图相关

1. 无向图判环(并查集方法)

2. 图的连通性问题(并查集)

3. 深度优先搜索(DFS)

4. 单源最短路算法:迪杰斯特拉算法

5. 多源最短路算法:弗洛伊德算法

6. 有向图:拓扑排序

九、数据处理

1. 主数据离散化

2. 静态区间最值(RMQ 问题,ST 表)

十、字符串相关

1. 字符串前缀匹配

2. 字符串模式匹配(KMP 算法)

3. 最长回文子串

十一、总结


一、引言

计算机算法和数据结构是编程领域的基石,它们为解决各种复杂问题提供了高效的解决方案。本文将汇总视频中涉及的计算机算法和数据结构知识点,并给出相应的 C++ 代码实现。

二、队列与栈

1. 先进先出队列

队列是一种遵循先进先出(FIFO)原则的数据结构。在 C++ 中,可以使用 std::queue 来实现。

#include <iostream>
#include <queue>

int main() {
    std::queue<int> q;
    q.push(1);
    q.push(2);
    q.push(3);

    while (!q.empty()) {
        std::cout << q.front() << " ";
        q.pop();
    }
    std::cout << std::endl;
    return 0;
}

2. 后进先出栈

栈是一种遵循后进先出(LIFO)原则的数据结构。在 C++ 中,可以使用 std::stack 来实现。

#include <iostream>
#include <stack>

int main() {
    std::stack<int> s;
    s.push(1);
    s.push(2);
    s.push(3);

    while (!s.empty()) {
        std::cout << s.top() << " ";
        s.pop();
    }
    std::cout << std::endl;
    return 0;
}

三、滑动窗口

滑动窗口最大值问题

给定一个数组和一个固定大小的窗口,求每个窗口内的最大值。可以使用双端队列来解决。

#include <iostream>
#include <vector>
#include <deque>

std::vector<int> maxSlidingWindow(std::vector<int>& nums, int k) {
    std::vector<int> result;
    std::deque<int> dq;

    for (int i = 0; i < nums.size(); ++i) {
        if (!dq.empty() && dq.front() == i - k) {
            dq.pop_front();
        }
        while (!dq.empty() && nums[dq.back()] < nums[i]) {
            dq.pop_back();
        }
        dq.push_back(i);
        if (i >= k - 1) {
            result.push_back(nums[dq.front()]);
        }
    }
    return result;
}

四、数组查找

有序数组的二分查找

二分查找是一种在有序数组中查找特定元素的高效算法。

#include <iostream>
#include <vector>

int binarySearch(std::vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

五、动态规划

查找最长递增子序列

使用动态规划算法来查找最长递增子序列。

#include <iostream>
#include <vector>
#include <algorithm>

int lengthOfLIS(std::vector<int>& nums) {
    if (nums.empty()) return 0;
    std::vector<int> dp(nums.size(), 1);
    for (int i = 0; i < nums.size(); ++i) {
        for (int j = 0; j < i; ++j) {
            if (nums[j] < nums[i]) {
                dp[i] = std::max(dp[i], dp[j] + 1);
            }
        }
    }
    return *std::max_element(dp.begin(), dp.end());
}

六、排序与统计

数组中逆序对统计

使用归并排序思想来统计数组中的逆序对。

#include <iostream>
#include <vector>

int mergeSort(std::vector<int>& nums, int left, int right) {
    if (left >= right) return 0;
    int mid = left + (right - left) / 2;
    int count = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right);

    std::vector<int> temp(right - left + 1);
    int i = left, j = mid + 1, k = 0;
    while (i <= mid && j <= right) {
        if (nums[i] <= nums[j]) {
            temp[k++] = nums[i++];
        } else {
            temp[k++] = nums[j++];
            count += mid - i + 1;
        }
    }
    while (i <= mid) temp[k++] = nums[i++];
    while (j <= right) temp[k++] = nums[j++];
    for (i = left, k = 0; i <= right; ++i, ++k) {
        nums[i] = temp[k];
    }
    return count;
}

int reversePairs(std::vector<int>& nums) {
    return mergeSort(nums, 0, nums.size() - 1);
}

七、集合操作

1. 快速获取集合重复值

可以使用哈希表来快速获取集合中的重复值。

#include <iostream>
#include <vector>
#include <unordered_set>

std::vector<int> findDuplicates(std::vector<int>& nums) {
    std::unordered_set<int> seen;
    std::unordered_set<int> duplicates;
    for (int num : nums) {
        if (seen.find(num) != seen.end()) {
            duplicates.insert(num);
        } else {
            seen.insert(num);
        }
    }
    return std::vector<int>(duplicates.begin(), duplicates.end());
}

2. 快速获取集合最值

可以使用 std::min_element 和 std::max_element 来快速获取集合的最值。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> nums = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
    auto minIt = std::min_element(nums.begin(), nums.end());
    auto maxIt = std::max_element(nums.begin(), nums.end());
    std::cout << "Min: " << *minIt << ", Max: " << *maxIt << std::endl;
    return 0;
}

八、图相关

1. 无向图判环(并查集方法)

#include <iostream>
#include <vector>

class UnionFind {
public:
    std::vector<int> parent;
    UnionFind(int n) {
        parent.resize(n);
        for (int i = 0; i < n; ++i) {
            parent[i] = i;
        }
    }
    int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }
    bool unite(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX == rootY) {
            return false;
        }
        parent[rootX] = rootY;
        return true;
    }
};

bool hasCycle(int n, std::vector<std::vector<int>>& edges) {
    UnionFind uf(n);
    for (auto& edge : edges) {
        if (!uf.unite(edge[0], edge[1])) {
            return true;
        }
    }
    return false;
}

2. 图的连通性问题(并查集)

#include <iostream>
#include <vector>

class UnionFind {
public:
    std::vector<int> parent;
    UnionFind(int n) {
        parent.resize(n);
        for (int i = 0; i < n; ++i) {
            parent[i] = i;
        }
    }
    int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }
    void unite(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            parent[rootX] = rootY;
        }
    }
    bool isConnected(int x, int y) {
        return find(x) == find(y);
    }
};

3. 深度优先搜索(DFS)

#include <iostream>
#include <vector>

void dfs(std::vector<std::vector<int>>& graph, int node, std::vector<bool>& visited) {
    visited[node] = true;
    std::cout << node << " ";
    for (int neighbor : graph[node]) {
        if (!visited[neighbor]) {
            dfs(graph, neighbor, visited);
        }
    }
}

4. 单源最短路算法:迪杰斯特拉算法

#include <iostream>
#include <vector>
#include <queue>
#include <limits>

using namespace std;
const int INF = numeric_limits<int>::max();

vector<int> dijkstra(const vector<vector<pair<int, int>>>& graph, int start) {
    int n = graph.size();
    vector<int> dist(n, INF);
    dist[start] = 0;
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    pq.push({0, start});

    while (!pq.empty()) {
        int u = pq.top().second;
        int d = pq.top().first;
        pq.pop();

        if (d > dist[u]) continue;

        for (const auto& edge : graph[u]) {
            int v = edge.first;
            int weight = edge.second;
            if (dist[u] + weight < dist[v]) {
                dist[v] = dist[u] + weight;
                pq.push({dist[v], v});
            }
        }
    }
    return dist;
}

5. 多源最短路算法:弗洛伊德算法

#include <iostream>
#include <vector>
#include <limits>

using namespace std;
const int INF = numeric_limits<int>::max();

void floydWarshall(vector<vector<int>>& graph) {
    int n = graph.size();
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (graph[i][k] != INF && graph[k][j] != INF) {
                    graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]);
                }
            }
        }
    }
}

6. 有向图:拓扑排序

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

vector<int> topologicalSort(const vector<vector<int>>& graph) {
    int n = graph.size();
    vector<int> inDegree(n, 0);
    for (int u = 0; u < n; ++u) {
        for (int v : graph[u]) {
            inDegree[v]++;
        }
    }

    queue<int> q;
    for (int i = 0; i < n; ++i) {
        if (inDegree[i] == 0) {
            q.push(i);
        }
    }

    vector<int> result;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        result.push_back(u);
        for (int v : graph[u]) {
            if (--inDegree[v] == 0) {
                q.push(v);
            }
        }
    }

    if (result.size() != n) {
        // 存在环
        return {};
    }
    return result;
}

九、数据处理

1. 主数据离散化

#include <iostream>
#include <vector>
#include <algorithm>

vector<int> discretize(vector<int>& nums) {
    vector<int> sortedNums = nums;
    sort(sortedNums.begin(), sortedNums.end());
    auto last = unique(sortedNums.begin(), sortedNums.end());
    sortedNums.erase(last, sortedNums.end());

    vector<int> result;
    for (int num : nums) {
        auto it = lower_bound(sortedNums.begin(), sortedNums.end(), num);
        result.push_back(it - sortedNums.begin());
    }
    return result;
}

2. 静态区间最值(RMQ 问题,ST 表)

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

class SparseTable {
private:
    vector<vector<int>> st;
    vector<int> log2;

public:
    SparseTable(const vector<int>& arr) {
        int n = arr.size();
        int k = log2_floor(n);
        st.resize(n, vector<int>(k + 1));

        for (int i = 0; i < n; ++i) {
            st[i][0] = arr[i];
        }

        for (int j = 1; (1 << j) <= n; ++j) {
            for (int i = 0; i + (1 << j) - 1 < n; ++i) {
                st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
            }
        }

        log2.resize(n + 1);
        for (int i = 2; i <= n; ++i) {
            log2[i] = log2[i / 2] + 1;
        }
    }

    int query(int l, int r) {
        int j = log2[r - l + 1];
        return min(st[l][j], st[r - (1 << j) + 1][j]);
    }

private:
    int log2_floor(int x) {
        return log2(x) / log2(2);
    }
};

十、字符串相关

1. 字符串前缀匹配

#include <iostream>
#include <string>

bool isPrefix(const std::string& str, const std::string& prefix) {
    if (prefix.length() > str.length()) return false;
    for (int i = 0; i < prefix.length(); ++i) {
        if (str[i] != prefix[i]) return false;
    }
    return true;
}

2. 字符串模式匹配(KMP 算法)

#include <iostream>
#include <vector>
#include <string>

std::vector<int> computeLPSArray(const std::string& pat) {
    int m = pat.length();
    std::vector<int> lps(m, 0);
    int len = 0;
    int i = 1;
    while (i < m) {
        if (pat[i] == pat[len]) {
            len++;
            lps[i] = len;
            i++;
        } else {
            if (len != 0) {
                len = lps[len - 1];
            } else {
                lps[i] = 0;
                i++;
            }
        }
    }
    return lps;
}

std::vector<int> KMPSearch(const std::string& txt, const std::string& pat) {
    int n = txt.length();
    int m = pat.length();
    std::vector<int> lps = computeLPSArray(pat);
    std::vector<int> indices;
    int i = 0;
    int j = 0;
    while (i < n) {
        if (pat[j] == txt[i]) {
            j++;
            i++;
        }
        if (j == m) {
            indices.push_back(i - j);
            j = lps[j - 1];
        } else if (i < n && pat[j] != txt[i]) {
            if (j != 0) {
                j = lps[j - 1];
            } else {
                i++;
            }
        }
    }
    return indices;
}

3. 最长回文子串

#include <iostream>
#include <string>

std::string longestPalindrome(const std::string& s) {
    if (s.empty()) return "";
    int start = 0, maxLen = 1;
    for (int i = 0; i < s.length(); ++i) {
        for (int j = i; j < s.length(); ++j) {
            int len = j - i + 1;
            bool isPalindrome = true;
            for (int k = 0; k < len / 2; ++k) {
                if (s[i + k] != s[j - k]) {
                    isPalindrome = false;
                    break;
                }
            }
            if (isPalindrome && len > maxLen) {
                maxLen = len;
                start = i;
            }
        }
    }
    return s.substr(start, maxLen);
}

十一、总结

本文汇总了视频中涉及的计算机算法和数据结构知识点,并给出了相应的 C++ 代码实现。这些知识点涵盖了队列、栈、滑动窗口、数组查找、动态规划、排序与统计、集合操作、图相关、数据处理和字符串相关等多个方面。掌握这些知识点和代码实现,将有助于提高编程能力和解决实际问题的能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值