LeetCode题解:Interleaving String的几种思路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jining11/article/details/83793919

题目要求

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

Example 1:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true

Example 2:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
Output: false

注意到interleaving的含义是交错,也就是说s1、s2在相互交错以连接为s3时,必须要保证其内部的字符是有序且不可跳过的。

极其简单的递归法

class Solution {
public:

	bool find(string s1, string s2, string s3) {
		if (s1+s2 == s3) {
			return true;
		}
		if (s1[0] == s3[0] && find(s1.substr(1), s2, s3.substr(1))) {
			return true;
		}
		if (s2[0] == s3[0] && find(s1, s2.substr(1), s3.substr(1))) {
			return true;
		}
		return false;
	}

    bool isInterleave(string s1, string s2, string s3) {
    	if (s1.size() + s2.size() != s3.size()) {
    		return false;
    	}
    	return find(s1, s2, s3);
    }
};

虽然算法很优美,但奈何还是倒在了timelimit这一关。
在这里插入图片描述

改进了一丢丢的深搜法

所以我们要想一下,为什么一开始的深搜会跑得那么慢,时间都消耗在哪一步了呢?递归最大的弊端在于重复计算,考虑这样一种情况:某时刻s1和s2的前5和前4个字符串构成了s3的前九个,记为(5,4)。接下来,是(6,4),(6,5)…但最终无法完成匹配。于是程序重新回到了(5,4),接下来是(5,5),(6,5),在上述那种算法下,就会重复计算(6,5)之后注定会错误的解。

改进思路:

  • 记录所走过的路径。
  • 考虑当s1已经全部加入s3时,只需比较s2和s3剩余的部分是否一致。
class Solution {
   int m[200][200];
public:

   bool dfs(string s1, string s2, string s3, int i1, int i2, int i3) {
   	if (m[i1][i2]) {
   		return false;
   	}
   	if (i2 == s2.size()) {
   		return (s1.substr(i1)==s3.substr(i3));
   	}
   	if (i1 == s1.size()) {
   		return (s2.substr(i2)==s3.substr(i3));
   	}
   	if (s1[i1] == s3[i3] && dfs(s1, s2, s3, i1+1, i2, i3+1)) {
   		return true;
   	}
   	if (s2[i2] == s3[i3] && dfs(s1, s2, s3, i1, i2+1, i3+1)) {
   		return true;
   	}
   	m[i1][i2] = 1;
   	return false;
   }

   bool isInterleave(string s1, string s2, string s3) {
   	if (s1.size() + s2.size() != s3.size()) {
   		return false;
   	}
   	return dfs(s1, s2, s3, 0, 0, 0);
   }
};

在这里插入图片描述

嘻嘻嘻,撒花儿~

猜你喜欢

转载自blog.csdn.net/jining11/article/details/83793919