蒟蒻的LeetCode刷题记录71~80

71. 简化路径
蒟蒻的LeetCode刷题记录71~80_第1张图片
类似于一个树的递归,但是可以直接用栈来实现:

class Solution {
     
public:
    string simplifyPath(string path) {
     
        string res, name;
        if (path.back() != '/') path += '/';
        for (auto c : path) {
     
            if (c != '/') name += c;
            else {
     
                if (name == "..") {
     
                    while (res.size() && res.back() != '/') res.pop_back();
                    if (res.size()) res.pop_back();
                } else if (name != "." && name != "") {
     
                    res += '/' + name;
                }
                name.clear();
            }
        }
        if (res.empty()) res = "/";
        return res;
    }
};

72. 编辑距离
蒟蒻的LeetCode刷题记录71~80_第2张图片
蒟蒻的LeetCode刷题记录71~80_第3张图片

class Solution {
     
public:
    int minDistance(string a, string b) {
     
        int n = a.size(), m = b.size();
        a = ' ' + a, b = ' ' + b;
        vector<vector<int>> f(n + 1, vector<int>(m + 1));
        //初始化
        for (int i = 0; i <= n; i ++ ) f[i][0] = i;//若a长度为i,b长度为0,则需要进行i次删除操作
        for (int i = 1; i <= m; i ++ ) f[0][i] = i;//若a长度为0,b长度为i,则需要进行i次添加操作

        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= m; j ++ ) {
     
                f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;//删除和添加
                int t = a[i] != b[j];
                f[i][j] = min(f[i][j], f[i - 1][j - 1] + t); //修改
            }

        return f[n][m];
    }
};

73. 矩阵置零
蒟蒻的LeetCode刷题记录71~80_第4张图片
蒟蒻的LeetCode刷题记录71~80_第5张图片

class Solution {
     
public:
    void setZeroes(vector<vector<int>>& matrix) {
     
        if (matrix.empty()) return;
        int n = matrix.size(), m = matrix[0].size();
        int col0 = 1, row0 = 1;
        for (int i = 0; i < n; i++)
            if (!matrix[i][0]) col0 = 0;
        for (int i = 0; i < m; i++)
            if (!matrix[0][i]) row0 = 0;
        for (int i = 1; i < n; i++)
            for (int j = 1; j < m; j++)
                if (!matrix[i][j]) {
     
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
        for (int i = 1; i < n; i++)
            if (!matrix[i][0])
                for (int j = 1; j < m; j++)
                    matrix[i][j] = 0;

        for (int i = 1; i < m; i++)
            if (!matrix[0][i])
                for (int j = 1; j < n; j++)
                    matrix[j][i] = 0;
        //最后处理第一行和第一列
        if (!row0) for (int j = 0; j < m; j++) matrix[0][j] = 0;
        if (!col0) for (int i = 0; i < n; i++) matrix[i][0] = 0;

    }
};

74. 搜索二维矩阵
方法一:
蒟蒻的LeetCode刷题记录71~80_第6张图片

class Solution {
     
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
     
        if (matrix.empty() || matrix[0].empty()) return false;
        int n = matrix.size(), m = matrix[0].size();

        int l = 0, r = n * m - 1;
        while (l < r) {
     
            int mid = l + r >> 1;
            if (matrix[mid / m][mid % m] >= target) r = mid;
            else l = mid + 1;
        }
        return matrix[r / m][r % m] == target;
    }
};

方法二:
剑指offer的方法:

class Solution {
     
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
     
        if (matrix.empty() || matrix[0].empty()) return false;
        int i = 0, j = matrix[0].size() - 1;
        while (i < matrix.size() && j >= 0) {
     
            if (matrix[i][j] == target) return true;
            if (matrix[i][j] < target) i++;
            else j--;
        }
        return false;
    }
};

75. 颜色分类
这题的思路很有跳跃性,不容易想到,而且只适用于这个做法。不过其实也算是一个 三指针算法。
蒟蒻的LeetCode刷题记录71~80_第7张图片

class Solution {
     
public:
    void sortColors(vector<int>& nums) {
     
        for (int i = 0, j = 0, k = nums.size() - 1; i <=k; ) {
     
            if (nums[i] == 0) swap(nums[i++], nums[j++]);
            else if (nums[i] == 2) swap(nums[i], nums[k--]);
            else i++;
        }
    }
};

其余的两种算法参见题解

76. 最小覆盖子串
和第三题比较类似。
蒟蒻的LeetCode刷题记录71~80_第8张图片

class Solution {
     
public:
    string minWindow(string s, string t) {
     
        unordered_map<char, int> hs, ht;//开两个哈希表来记录每个字符出现的次数
        for (int i = 0; i < t.size(); i++) ht[t[i]]++;//t里每个字符出现的次数

        string res;
        int cnt = 0;
        for (int i = 0, j = 0; i < s.size(); i++ ) {
     
            hs[s[i]]++ ;//s里每个字符出现的次数
            if (hs[s[i]] <= ht[s[i]]) cnt++ ;//s[i]加完不多余,则cnt++

            while (hs[s[j]] > ht[s[j]]) hs[s[j++ ]]-- ;//s中出现的次数严格大于t中的次数,则j可以向后移,并且将计数-1
            if (cnt == t.size()) {
     //有效窗口,找到了这样的一组值
                if (res.empty() || i - j + 1 < res.size())//满足条件则输出
                    res = s.substr(j, i - j + 1);
            }
        }
        return res;
    }
};

77. 组合
排列组合立马就想到dfs模板:
蒟蒻的LeetCode刷题记录71~80_第9张图片

class Solution {
     
public:
    vector<vector<int>> res;
    vector<int> path;

    vector<vector<int>> combine(int n, int k) {
     
        dfs(n, k, 1);
        return res;
    }

    void dfs(int n, int k, int start) {
     
        if (!k) {
     
            res.push_back(path);
            return;
        }

        for (int i = start; i <= n; i ++) {
     
            path.push_back(i);
            dfs(n, k - 1, i + 1);
            path.pop_back();
        }
    }
};

78. 子集
方法一:
蒟蒻的LeetCode刷题记录71~80_第10张图片

class Solution {
     
public:
    vector<vector<int>> subsets(vector<int>& nums) {
     
        vector<vector<int>> res;
        int n = nums.size();
        for (int i= 0; i < 1 << n; i++) {
     //一直枚举到2^n - 1位
            vector<int> path;
            for (int j = 0; j < n; j++) {
     //枚举一下每位是0还是1,代表选还是不选
                if (i >> j & 1) {
     //这里要看i的第j位,所以将第j位移到个位再&1,就知道是0还是1了
                    path.push_back(nums[j]);//如果是1说明要选,将其加到方案中
                }
            }
            res.push_back(path);//将当前方案记录到答案中
        }
        return res;
    }
};

方法二:
dfs:

class Solution {
     
public:
    vector<vector<int>> res;
    vector<int> path;

    vector<vector<int>> subsets(vector<int>& nums) {
     
        dfs(nums, 0);
        return res;    
    }

    void dfs(vector<int>& nums, int u) {
     
        if (u == nums.size()) {
     
            res.push_back(path);
            return;
        }

        dfs(nums, u + 1);//不选当前数,递归下一层
        path.push_back(nums[u]);//选当前数
        dfs(nums, u + 1);//递归下一层
        path.pop_back();//回溯,恢复现场
    }
};

79. 单词搜索
也是剑指的一个原题,dfs。
蒟蒻的LeetCode刷题记录71~80_第11张图片

class Solution {
     
public:
    bool exist(vector<vector<char>>& board, string word) {
     
        for (int i = 0; i < board.size(); i ++ ) {
     //从起点开始搜
            for (int j = 0; j < board[i].size(); j ++ ) {
     
                if (dfs(board, word, 0, i, j)) return true;
            }
        }
        return false;
    }
    int dx[4] = {
     -1, 0, 1, 0}, dy[4] = {
     0, 1, 0, -1};//上右下左四个方向
    //u表示当前搜到第几个位置,x、y表示起点
    bool dfs(vector<vector<char>>& board, string& word, int u, int x, int y) {
     
        if (board[x][y] != word[u]) return false;//当前位置的字符相等,返回false
        if (u == word.size() - 1) return true;//已经搜完了最后一个字符,返回true

        char t = board[x][y];//存一下当前位置是什么
        board[x][y] = '.';//标记已经用过
        for (int i = 0; i < 4; i ++ ) {
     
            int a = x + dx[i], b = y + dy[i];
            //判断是否越界或者被用过
            if (a < 0 || a >= board.size() || b < 0 || b >= board[0].size() || board[a][b] == '.') continue;
            if (dfs(board, word, u + 1, a, b)) return true;//没有越界或者被用过则递归下一个
        }
        board[x][y] = t;//恢复现场
        return false;
    }
};

80. 删除排序数组中的重复项 II
和之前的第26题是一样的思路,只不过要保留两个而已。
蒟蒻的LeetCode刷题记录71~80_第12张图片

class Solution {
     
public:
    int removeDuplicates(vector<int>& nums) {
     
        int k = 0;
        for (int i = 0; i < nums.size(); i++) {
     
            if (k < 2 || nums[k - 1] != nums[i] || nums[k - 2] != nums[i])
                nums[k++] = nums[i];
        }
        return k;
    }
};

你可能感兴趣的:(Leetcode,学习笔记,刷题练习)