[Algorithm][综合训练][数组中两个字符串的最小距离][Fibonacci数列][单词搜索]详细讲解

目录

  • 1.数组中两个字符串的最小距离
    • 1.题目链接
    • 2.算法原理详解 && 代码实现
  • 2.Fibonacci数列
    • 1.题目链接
    • 2.算法原理详解 && 代码实现
  • 3.单词搜索
    • 1.题目链接
    • 2.算法原理详解 && 代码实现


1.数组中两个字符串的最小距离

1.题目链接

  • 数组中两个字符串的最小距离

2.算法原理详解 && 代码实现

  • 自己的版本85% 贪心
    • 错误原因:这样贪心只是一直在往后找两组可能的新的str来更新最小值,但是前面仍然有可能存在最优解的情况
    • 错误版本
      #include 
      #include 
      #include 
      #include 
      #include 
      using namespace std;
      
      int main()
      {
          int n = 0;
          string str1, str2;
          cin >> n >> str1 >> str2;
          
          vector<string> strs(n);
          for(int i = 0; i < n; i++)
          {
              cin >> strs[i];
          }
      
          if(str1.empty() && str2.empty())
          {
              cout << -1 << endl;
              return 0;
          }
          
          // 双指针
          int p1 = 0, p2 = 0, ret1 = 0, ret2 = 0, minDist = INT_MAX;
          bool flag1 = false, flag2 = false;
      
          while(p1 < n && p2 < n)
          {
              // 找str1
              while(p1 < n)
              {
                  if(strs[p1] == str1)
                  {
                      flag1 = true;
                      ret1 = p1++;
                      break;
                  }
      
                  p1++;
              }
      
              // 找str2
              while(p2 < n)
              {
                  if(strs[p2] == str2)
                  {
                      flag2 = true;
                      ret2 = p2++;
                      break;
                  }
      
                  p2++;
              }
      
              if(flag1 && flag2)
              {
                  minDist = min(minDist, abs(ret1 - ret2));
              }
          }
      
          cout << (minDist == INT_MAX ? -1 : minDist) << endl;
      
          return 0;
      }
      
    • 纠正:每次找到一个str就应该更新一次minDist,而不是等两个查找str都跑完再更新
      #include 
      #include 
      #include 
      #include 
      #include 
      using namespace std;
      
      int main()
      {
      	int n = 0;
      	string str1, str2;
      	cin >> n >> str1 >> str2;
      
      	vector<string> strs(n);
      	for (int i = 0; i < n; i++)
      	{
      		cin >> strs[i];
      	}
      
      	if (str1.empty() && str2.empty())
      	{
      		cout << -1 << endl;
      		return 0;
      	}
      
      	// 双指针
      	int p1 = 0, p2 = 0, ret1 = 0, ret2 = 0, minDist = INT_MAX;
      	bool flag1 = false, flag2 = false;
      
      	while (p1 < n || p2 < n)
      	{
      		// 找str1
      		while (p1 < n)
      		{
      			if (strs[p1] == str1)
      			{
      				flag1 = true;
      				ret1 = p1++;
      				break;
      			}
      
      			p1++;
      		}
      		if (flag1 && flag2)
      		{
      			minDist = min(minDist, abs(ret1 - ret2));
      		}
      
      		// 找str2
      		while (p2 < n)
      		{
      			if (strs[p2] == str2)
      			{
      				flag2 = true;
      				ret2 = p2++;
      				break;
      			}
      
      			p2++;
      		}
      		if (flag1 && flag2)
      		{
      			minDist = min(minDist, abs(ret1 - ret2));
      		}
      	}
      
      	cout << (minDist == INT_MAX ? -1 : minDist) << endl;
      
      	return 0;
      }
      
  • 优化版本贪心(预处理) --> 用几个变量去标记目前已经发现的值
    #include 
    #include 
    using namespace std;
    
    int main()
    {
    	int n = 0;
    	string str1, str2, str; // str用于优化空间,没必要用一个vector存储
    	cin >> n >> str1 >> str2;
    
    	int prev1 = -1, prev2 = -1, ret = 0x3f3f3f3f;
    	for(int i = 0; i < n; i++) // 用i去同时探寻str1和str2
    	{
    		cin >> str;
    		if(str == str1) // 去前面找最近的str2
    		{
    			if(prev2 != -1)
    			{
    				ret = min(ret, i - prev2);
    			}
    
    			prev1 = i;
    		}
    		else if(str == str2) // 去前面找最近的str1
    		{
    			if(prev1 != -1)
    			{
    				ret = min(ret, i - prev1);
    			}
    
    			prev2 e= i;
    		}
    	}
    
    	cout << (ret == 0x3f3f3f3f ? -1 : ret) << endl;
    
    	return 0;
    }
    

2.Fibonacci数列

1.题目链接

  • Fibonacci数列

2.算法原理详解 && 代码实现

  • 自己的版本
    #include 
    #include 
    using namespace std;
    
    int main()
    {
        int n = 0;
        cin >> n;
    
        // 动态规划计算Fib
        vector<int> fib(2, 0);
        fib[0] = 0, fib[1] = 1;
    
        int i = 2;
        while(true)
        {
            fib.push_back(fib[i - 1] + fib[i - 2]);
    
            if(fib[i++] > n)
            {
                break;
            }
        }
    
        int prevDist = n - fib[i - 2], nextDist = fib[i - 1] - n;
        cout <<  (prevDist < nextDist ? prevDist : nextDist) << endl;
    
        return 0;
    }
    
  • 优化版本:相较自己的版本进行了空间优化
    #include 
    using namespace std;
    
    int main()
    {
        int n = 0;
        cin >> n;
        
     	int a = 0, b = 1, c = 1;
        while(n > c)
        {
            a = b;
            b = c;
            c = a + b;
        }
        
        cout << min(c - n, n - b);
        
        return 0;
    }
    

3.单词搜索

1.题目链接

  • 单词搜索

2.算法原理详解 && 代码实现

  • 自己的版本纯暴搜,因为超时而64.25%
    class Solution
    {
        int n = 0, m = 0;
        int dx[4] = {1, -1, 0, 0};
        int dy[4] = {0, 0, 1, -1};
        vector<vector<bool>> visit;
        string _word, path;
    
        bool exist(vector<string>& board, string word)
        {
            n = board.size(), m = board[0].size();
            visit.resize(n, vector<bool>(m, false));
            _word = word;
    
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < m; j++)
                {
                    path += board[i][j];
                    visit[i][j] = true;
    
                    if(DFS(board, i, j))
                    {
                        return true;
                    }
    
                    path.pop_back(); // 回溯
                    visit[i][j] = false;
                }
            }
    
            return false;
        }
    
        bool DFS(vector<string>& board, int row, int col)
        {
            if(path == _word)
            {
                return true;
            }
    
            for(int k = 0; k < 4; k++)
            {
                int i = row + dx[k], j = col + dy[k];
    
                if(i < n && i >= 0 && j < m && j >= 0 && !visit[i][j])
                {
                    visit[i][j] = true;
                    path += board[i][j];
    
                    if(DFS(board, i, j))
                    {
                        return true;
                    }
    
                    // 回溯
                    visit[i][j] = false;
                    path.pop_back();
                }
            }
    
            return false;
        }
    };
    
  • 优化版本:相较于自己的版本,做了剪枝和空间优化
    class Solution
    {
        int n = 0, m = 0;
        vector<vector<bool>> visit;
        
        int dx[4] = {1, -1, 0, 0};
        int dy[4] = {0, 0, 1, -1};
    public:
        bool exist(vector<string>& board, string word)
        {
        	n = board.size(), m = board[0].size();
            visit.resize(n, vector<bool>(m, false));
            
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < m; j++)
                {
                    if(board[i][j] == word[0]) // 剪枝
                    {
                        if(DFS(board, i, j, word, 0))
                        {
                            return true;
                        }
                    }
                }
            }
            
            return false;
        }
        
        bool DFS(vector<string>& board, int i, int j, string& word, int pos)
        {
            if(pos == word.size() - 1)
            {
                return true;
            }
            
            visit[i][j] = true;
            for(int k = 0; k < 4; k++)
            {
                int a = i + dx[k], b = j + dy[k];
                if(a >= 0 && a < n && b >= 0 && b < m && 
                   !visit[a][b] && board[a][b] == word[pos + 1]) // 剪枝
                {
                    if(DFS(board, a, b, word, pos + 1))
                    {
                        return true;
                    }
                }
            }
            visit[i][j] = false;
            
            return false;
        }
    };
    

你可能感兴趣的:([OJ],#,[综合训练],算法,Algorithm,综合训练,数组中两个字符串的最小距离,Fibonacci数列,单词搜索,详细讲解)