71. 简化路径
类似于一个树的递归,但是可以直接用栈来实现:
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;
}
};
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];
}
};
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;
}
};
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. 颜色分类
这题的思路很有跳跃性,不容易想到,而且只适用于这个做法。不过其实也算是一个双 三指针算法。
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++;
}
}
};
其余的两种算法参见题解
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;
}
};
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();
}
}
};
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();//回溯,恢复现场
}
};
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题是一样的思路,只不过要保留两个而已。
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;
}
};