[LEECODE]算法进阶自练习9-10 图&堆和排序

280 阅读2分钟

[LEECODE]算法进阶自练习9-10 图&堆和排序

9.图

中等
  1. 岛屿数量 leetcode 200  BFS解法:
    int numIslands(vector<vector<char>>& grid) {
        int count = 0, m = grid.size();
        if(m == 0) return 0;
        int n = grid[0].size();
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(grid[i][j] == '1'){
                    grid[i][j] = '0';
                    count++;
                    queue<pair<int,int>> que;
                    que.push({i,j});
                    while(!que.empty()){
                        auto t = que.front();
                        que.pop();
                        int r = t.first, c = t.second;
                        if(r-1>=0 && grid[r-1][c] == '1') {
                            grid[r-1][c] = '0';
                            que.push({r-1,c});
                        }
                        if(r+1<m && grid[r+1][c] == '1') {
                            grid[r+1][c] = '0';
                            que.push({r+1,c});
                        }
                        
                        if(c-1>=0 && grid[r][c-1] == '1') {
                            grid[r][c-1] = '0';
                            que.push({r,c-1});
                        }
                        if(c+1<n && grid[r][c+1] == '1') {
                            grid[r][c+1] = '0';
                            que.push({r,c+1});
                        }
                    }
                    
                }
            }
        }
        return count;
    }

 DFS解法:

    void disIsland(vector<vector<char>>& grid, int i, int j){
        int m = grid.size(), n = grid[0].size();
        grid[i][j] = '0';
        if(i-1 >= 0 && grid[i-1][j] == '1') disIsland(grid, i-1, j);
        if(i+1 < m && grid[i+1][j] == '1') disIsland(grid, i+1, j);
        if(j-1 >= 0 && grid[i][j-1] == '1') disIsland(grid, i, j-1);
        if(j+1 < n && grid[i][j+1] == '1') disIsland(grid, i, j+1);
    }
    int numIslands(vector<vector<char>>& grid) {
        int count = 0, m = grid.size();
        if(m == 0) return 0;
        int n = grid[0].size();
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(grid[i][j] == '1'){
                    disIsland(grid, i, j);
                    count++;
                }
            }
        }
        return count;
    }

 并查集解法:

class UnionFind{
    private:
    vector<int> rank;
    vector<int> parent;
    int count;

    public:
    UnionFind(vector<vector<char>>& grid){
        count = 0;
        int m = grid.size(), n = grid[0].size();
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(grid[i][j] == '1'){
                    parent.push_back(i*n+j);
                    ++count;
                }
                else{
                    parent.push_back(-1);
                }
                rank.push_back(0);
            }
        }
    }
    int find(int i){
        if(i != parent[i]) parent[i] = find(parent[i]);
        return parent[i];
    }
    void punion(int x, int y){
        int rx = find(x), ry = find(y);
        if(rx != ry){
            if(rank[rx] < rank[ry]) swap(rank[rx],rank[ry]);
            parent[rx] = parent[ry];
            if(rank[rx] == rank[ry]) rank[rx] += 1;
            --count;
        }
        
    }
    int getCount() const { return count; }
};

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size();
        if(!m) return 0;
        int n = grid[0].size();
        UnionFind uf(grid);
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(grid[i][j] == '1'){
                    grid[i][j] = '0';
                    if(i-1 >= 0 && grid[i-1][j] == '1') uf.punion(i*n+j,(i-1)*n+j);
                    if(i+1 < m && grid[i+1][j] == '1') uf.punion(i*n+j,(i+1)*n+j);
                    if(j-1 >= 0 && grid[i][j-1] == '1') uf.punion(i*n+j, i*n+j-1);
                    if(j+1 < n && grid[i][j+1] == '1') uf.punion(i*n+j, i*n+j+1);
            
                }
            }
        }
        return uf.getCount();
    }
};
  1. 课程表II leetcode 210  DFS解法:
class Solution {
    vector<vector<int>> edges;
    vector<int> visited;
    vector<int> result;
    bool valid = true; // 是否有环

public:
    void dfs(int i){
        // 标记为搜索中
        visited[i] = 1;
        // 查找所有边
        for(int v: edges[i]){
            if(visited[v] == 0){
                dfs(v);
                if(!valid){
                    return;
                }
            }
            else if(visited[v] == 1){
                valid = false;
                return;
            }
        }
        visited[i] = 2;
        result.push_back(i);

    }
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        visited.resize(numCourses);
        for(const auto& info:prerequisites){
            edges[info[1]].push_back(info[0]);
        }
        for(int i=0; i<numCourses && valid; i++){
            if(!visited[i]){
                dfs(i);
            }
        }
        if(!valid){
            return {};
        }
        reverse(result.begin(),result.end());
        return result;
    }
};

 BFS解法:

class Solution {
    vector<vector<int>> edges;
    vector<int> indeg;
    vector<int> result;

public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        indeg.resize(numCourses);
        for(const auto& info:prerequisites){
            edges[info[1]].push_back(info[0]);
            ++indeg[info[0]];
        }
        queue<int> q;
        // 没有被依赖的课程可以先修
        for(int i=0; i<numCourses; i++){
            if(indeg[i] == 0){
                q.push(i);
            }
        }
        while(!q.empty()){
            int u = q.front();
            q.pop();
            result.push_back(u);
            for(int v: edges[u]){
                --indeg[v];
                if(indeg[v] == 0){
                    q.push(v);
                }
            }
        }
        if(result.size() != numCourses){
            return {};
        }
        return result;
    }
};

10.堆和排序

简单
  1. 数据流中第K大元素 leetcode 703  使用multiset解法:
class KthLargest {
    multiset<int> s;
    int K;
public:
    KthLargest(int k, vector<int>& nums) {
        for(int num : nums){
            s.insert(num);
            if(s.size() > k) s.erase(s.begin());
        }
        K = k;
    }
    
    int add(int val) {
        s.insert(val);
        if(s.size() > K) s.erase(s.begin());
        return *s.begin();
    }
};

 使用priority_queue解法:

class KthLargest {
    priority_queue<int, vector<int>, greater<int>> pq;
    int K;
public:
    KthLargest(int k, vector<int>& nums) {
        for(int num : nums){
            pq.push(num);
            if(pq.size() > k) pq.pop();
        }
        K = k;
    }
    
    int add(int val) {
        pq.push(val);
        if(pq.size() > K) pq.pop();
        return pq.top();
    }
};
中等
  1. 数据流的中位数 leetcode 295  基础排序解法,不能AC:
class MedianFinder {
public:
    vector<double> vec;
    /** initialize your data structure here. */
    MedianFinder() {

    }
    
    void addNum(int num) {
        vec.emplace_back(num);
    }
    
    double findMedian() {
        sort(vec.begin(),vec.end());
        int vsize = vec.size();
        return (double) (vsize&1 ? vec[vsize/2] : (vec[vsize/2] + vec[vsize/2-1])/2);
    }
};

 二分查找插入排序,不能AC:

class MedianFinder {
public:
    vector<double> vec;
    /** initialize your data structure here. */
    MedianFinder() {

    }
    
    void addNum(int num) {
        if(vec.empty()){
            vec.emplace_back(num);
        }
        else{
            vec.insert(lower_bound(vec.begin(),vec.end(), num),num);
        }
    }
    
    double findMedian() {
        sort(vec.begin(),vec.end());
        int vsize = vec.size();
        return (double) (vsize&1 ? vec[vsize/2] : (vec[vsize/2] + vec[vsize/2-1])/2);
    }
};

 priority_queue两个堆一大一小方法:

class MedianFinder {
public:
    priority_queue<int> prevH; // 最大堆
    priority_queue<int,vector<int>,greater<int>> nextH; // 最小堆

    /** initialize your data structure here. */
    MedianFinder() {

    }
    
    void addNum(int num) {
        prevH.push(num);
        nextH.push(prevH.top());
        prevH.pop();
        if(prevH.size() < nextH.size()){
            prevH.push(nextH.top());
            nextH.pop();
        }
    }
    
    double findMedian() {
        return (double)(prevH.size()>nextH.size() ? prevH.top() : (double)(prevH.top() + nextH.top())/2); // 后面的double一定要有不然会丢精度
    }
};

 multiset+双指针解法:

class MedianFinder {
public:
    multiset<int> st;
    multiset<int>::iterator left, right;
    /** initialize your data structure here. */
    MedianFinder():left(st.end()),right(st.end()) {

    }
    
    void addNum(int num) {
        int ssize = st.size();
        st.insert(num);
        if(!ssize){ // 原先size==0
            left = right = st.begin();
            return;
        }
        if(ssize&1){
            // 奇数个数
            (num < *left) ? left-- : right++;
        }
        else{
            // 偶数个数
            if(*left < num && *right > num){
                left++; right--;
            }else if(*right <= num){
                left++;
            }else{
                left = --right; // 注意这里 equal_range
            }
            
        }
    }
    
    double findMedian() {
        return (double)(*left + *right)/2;
    }
};