您的位置:首页 > 其它

【LeetCode71-80】71目录简化72DP问题73巧妙利用0位置76通用substr问题精妙模板79DFS+回溯

2017-04-12 21:01 483 查看

71.Unix风格的目录简化

//题目释义摘录自:链接

这道题的要求是简化一个Unix风格下的文件的绝对路径。

字符串处理,由于".."是返回上级目录(如果是根目录则不处理),因此可以考虑用栈记录路径名,以便于处理。需要注意几个细节:

重复连续出现的'/',只按1个处理,即跳过重复连续出现的'/';

如果路径名是".",则不处理;

如果路径名是"..",则需要弹栈,如果栈为空,则不做处理;

如果路径名为其他字符串,入栈。

最后,再逐个取出栈中元素(即已保存的路径名),用'/'分隔并连接起来,不过要注意顺序呦。

class Solution {
public:
string simplifyPath(string test ) {
string path = test + "/";

vector<string>temp_result;
string result = "/";
int j = 0;
string temp;
for (int i = 0; i<path.size(); ++i) {
if (path[i] == '/') {
temp = path.substr(j, i - j);
j = i + 1;
if (temp.size()>0) {
if (temp == "..") { if(!temp_result.empty())temp_result.pop_back(); }
else if (temp == ".") {}
else { temp_result.push_back(temp); }
}
}
}
for (int i = 0; i < temp_result.size(); ++i)result +=(i==0)? temp_result[i]:("/"+ temp_result[i]);
return result;
}
};


别人的方法//碉堡的getline 用法!!
stringstream用法

auto i: vector用法!!

class Solution {
public:
string simplifyPath(string path ) {
stringstream ss(path);
vector<string>temp_result;
string temp,result;
while(getline(ss,temp,'/')){
if(temp==""||temp==".")continue;
if(temp==".."&!temp_result.empty()){temp_result.pop_back();}
else if(temp!="..")temp_result.push_back(temp);
}
for(auto i:temp_result)result+="/"+i;
return result.empty()?"/":result;
}
};




72.两个单词之间最短距离【一定要再看看】DP问题,迭代的思路!

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character

b) Delete a character

c) Replace a character

只允许插入,删除和替换操作,计算最短步数使得单词1变成单词2

参考别人的思路:

Use f[i][j] to represent the shortest edit distance between word1[0,i) and word2[0, j). Then compare the last character of word1[0,i) and word2[0,j), which are c and d respectively (c == word1[i-1], d == word2[j-1]):

if c == d, then : f[i][j] = f[i-1][j-1]

Otherwise we can use three operations to convert word1 to word2:

(a) if we replaced c with d: f[i][j] = f[i-1][j-1] + 1;

(b) if we added d after c: f[i][j] = f[i][j-1] + 1;

(c) if we deleted c: f[i][j] = f[i-1][j] + 1;

Note that f[i][j] only depends on f[i-1][j-1], f[i-1][j] and f[i][j-1], therefore we can reduce the space to O(n) by using only the (i-1)th array and previous updated element(f[i][j-1]).

class Solution {
public:
int minDistance(string word1, string word2) {
//DP搜索
const int m = word1.size();
const int n = word2.size();
vector<vector<int>>result(m+1, vector<int>(n+1, 0));
for (int i = 0; i < m + 1; i++)result[i][0] = i;
for (int i = 0; i < n + 1; i++)result[0][i] = i;
for (int i = 1; i < m + 1; i++) {
for (int j = 1; j < n + 1; j++) {
if (word1[i - 1] == word2[j - 1])result[i][j] = result[i - 1][j - 1];
else result[i][j] = std::min(result[i - 1][j], std::min(result[i - 1][j - 1], result[i][j - 1]))+1;
}
}
return result[m]
;
}
};


73.设置矩阵0(对应行列改为0)空间限制O(1)

如果某个位置为0,所在的行和列全填充为0.

只允许O(1)的存储空间

class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int rows=matrix.size(),cols=matrix[0].size();
int first_col=1,first_row=1;
for(int i=0;i<cols;++i){if(matrix[0][i]==0)first_row=0;}
for(int i=0;i<rows;++i){if(matrix[i][0]==0)first_col=0;}
for(int i=1;i<cols;++i){
for(int j=1;j<rows;++j){
if(matrix[j][i]==0){
matrix[j][0]=0;
matrix[0][i]=0;
}
}
}

for(int j=1;j<rows;j++){
for(int i=1;i<cols;i++){
if(matrix[j][0]==0 || matrix[0][i]==0)matrix[j][i]=0;
}
}
if(first_col==0){for(int i=0;i<rows;++i)matrix[i][0]=0;}
if(first_row==0){for(int i=0;i<cols;++i)matrix[0][i]=0;}
return;
}
};




74.遍历二维排过序的数组

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

Integers in each row are sorted from left to right.
The first integer of each row is greater than the last integer of the previous row.

For example,

Consider the following matrix:
[
[1,   3,  5,  7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]


我的思路:当成一维的做……用二分查找…

class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size()==0||matrix[0].size()==0)return false;
int m=matrix.size(),n=matrix[0].size();
int left=0,right=m*n-1;
int mid=(left+right)/2;
while(left<right-1){
if(matrix[mid/n][mid%n]==target)return true;
else if(matrix[mid/n][mid%n]>target)right=mid;
else left=mid;
mid=(left+right)/2;
}
if(matrix[left/n][left%n]==target||matrix[right/n][right%n]==target)return true;
return false;
}
};


75.只包含0,1,2三个数字数组的排序

class Solution {
public:
void sortColors(vector<int>& nums) {
unordered_map<int,int>mapping;
for(int i=0;i<nums.size();++i)mapping[nums[i]]++;
for(int i=0;i<mapping[0];++i)nums[i]=0;
for(int i=mapping[0];i<mapping[0]+mapping[1];++i)nums[i]=1;
for(int i=mapping[0]+mapping[1];i<mapping[0]+mapping[1]+mapping[2];++i)nums[i]=2;
return;
}
};


76.包含指定字符的最小字串【Hard】

For example,

S =
"ADOBECODEBANC"


T =
"ABC"


Minimum window is
"BANC"
.

别人的优雅的代码:

class Solution {
public:

string minWindow(string s, string t) {
vector<int> map(128, 0);
for (auto c : t) map[c]++;//对t编码,每种字符出现次数
int counter = t.size(), begin = 0, end = 0, d = INT_MAX, head = 0;
while (end < s.size()) {//end从头遍历到尾
if (map[s[end++]]-- > 0) counter--; //如果counter为0说明从头到尾包含了所有的
while (counter == 0) { //
if (end - begin < d)  d = end - (head = begin);//下一句的begin++保证了d的最小
if (map[s[begin++]]++ == 0) counter++;  //make it invalid
}
}
return d == INT_MAX ? "" : s.substr(head, d);
}
};


几乎所有截取一段字符的问题都可以用下面一段代码!不能更优美…

int findSubstring(string s){
vector<int> map(128,0);
int counter; // check whether the substring is valid
int begin=0, end=0; //two pointers, one point to tail and one  head
int d; //the length of substring

for() { /* initialize the hash map here */ }

while(end<s.size()){

if(map[s[end++]]-- ?){  /* modify counter here */ }

while(/* counter condition */){

/* update d here if finding minimum*/

//increase begin to make it invalid/valid again

if(map[s[begin++]]++ ?){ /*modify counter here*/ }
}

/* update d here if finding maximum*/
}
return d;
}




77.1-n中所有k个数字的组合

好久没迭代了,都手生了!!……

//构造一个用以迭代的函数…

class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>>result;
vector<int>temp;
help(n,k,result,temp,1);
return result;
}
void help(int n,int k,vector<vector<int>>&result,vector<int>&temp,int i){
if(i>n+1)return;
if(temp.size()==k){result.push_back(temp);return;}
temp.push_back(i);help(n,k,result,temp,i+1);
temp.erase(temp.end()-1);help(n,k,result,temp,i+1);
}
};


78.又是一道迭代(2的n次方种)求所有子集

If nums =
[1,2,3]
, a solution
is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]


class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>>result;
vector<int>temp;
help(result,nums,temp,0);
return result;
}
void help(vector<vector<int>>&result,vector<int>&nums,vector<int>&temp,int i){
//if(i>temp.size())return;
if(i==nums.size()){result.push_back(temp);return;}
temp.push_back(nums[i]);help(result,nums,temp,i+1);
temp.erase(temp.end()-1);help(result,nums,temp,i+1);
}
};


79.二维图搜索(不允许走之前走过的路,迭代)Typical dfs+backtracking question(DFS+回溯法)

For example,

Given board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]

word =
"ABCCED"
,
-> returns
true
,

word =
"SEE"
,
-> returns
true
,

word =
"ABCB"
,
-> returns
false
.

我的方法:89ms...

class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if(word=="")return true;
unordered_map<int,int>mapping;

for(int i=0;i<board.size();++i){
for(int j=0;j<board[0].size();++j){
if(board[i][j]==word[0]){
if(help(board,word,1,i,j,mapping))return true;
}
}
}
return false;
}
bool help(vector<vector<char>>board,string word,int i,int m,int n,unordered_map<int,int>&mapping){
if(i==word.size())return true;
mapping[m*board[0].size()+n]=1;
if(m+1<board.size()&&board[m+1]
==word[i]){if(mapping[(m+1)*board[0].size()+n]!=1&&help(board,word,i+1,m+1,n,mapping))return true;}
if(n+1<board[0].size()&&board[m][n+1]==word[i]){if(mapping[m*board[0].size()+n+1]!=1&&help(board,word,i+1,m,n+1,mapping))return true;}
if(m-1>=0&&board[m-1]
==word[i]){if(mapping[(m-1)*board[0].size()+n]!=1&&help(board,word,i+1,m-1,n,mapping))return true;}
if(n-1>=0&&board[m][n-1]==word[i]){if(mapping[m*board[0].size()+n-1]!=1&&help(board,word,i+1,m,n-1,mapping))return true;}
mapping[m*board[0].size()+n]=0;
return false;
}
};


别人的DFS+Backtracking,16ms

class Solution {
private:
bool dfs(vector<vector<char>>& board, int row, int col, const string &word, int start, int M, int N, int sLen)
{
char curC;
bool res = false;
if( (curC = board[row][col]) != word[start]) return false;
if(start==sLen-1) return true;
board[row][col] = '*';
if(row>0) res = dfs(board, row-1, col, word, start+1, M, N, sLen);
if(!res && row < M-1) res = dfs(board, row+1, col, word, start+1, M, N, sLen);
if(!res && col > 0)   res = dfs(board, row, col-1, word, start+1, M, N, sLen);
if(!res && col < N-1) res = dfs(board,  row, col+1, word, start+1, M, N, sLen);
board[row][col] = curC;
return res;
}

public:
bool exist(vector<vector<char>>& board, string word) {
int M,N,i,j,sLen = word.size();
if( (M=board.size()) && (N=board[0].size()) && sLen)
{
for(i=0; i<M; ++i)
for(j=0; j<N; ++j)
if(dfs(board, i, j, word, 0, M, N, sLen)) return true;
}
return false;
}
};


80.sorted数组里保证每个数字至多两次

和26题类似,把多于两个的earse掉就好

class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int length=nums.size();//因为nums一直变短,所以需要length,毕竟nums.size()只调用一次
for(int i=0;i<length-2;++i){
if(nums[i]==nums[i+1]&&nums[i]==nums[i+2]){
nums.erase(nums.begin()+i);
--i;--length;
}
}
return nums.size();
}
};


安安静静地陪着建模,233(•‾̑⌣‾̑•)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐