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

本文解析了多道经典算法题目,包括Unix风格路径简化、编辑距离计算、矩阵置零等,涵盖了字符串处理、动态规划、矩阵操作等多个方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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][n];
	}
};


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][n]==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][n]==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(•‾̑⌣‾̑•)





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱铭德

五毛也是爱٩(●´৺`●)૭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值