1. 程式人生 > 實用技巧 >leetcode 97:交錯字串

leetcode 97:交錯字串

package com.example.lettcode.dailyexercises;

/**
 * @Class IsInterleave
 * @Description 97 交錯字串
 * 給定三個字串 s1, s2, s3, 驗證 s3 是否是由 s1 和 s2 交錯組成的。
 * <p>
 * 示例 1:
 * 輸入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
 * 輸出: true
 * <p>
 * 示例 2:
 * 輸入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
 * 輸出: false
 * @Author
 * @Date 2020/7/18
 **/
public class IsInterleave {
}
/**
 * error
 * 雙指標
 * 這種方式有可能因為前面交替順序不對,導致結果不對,應該加上回溯
 * s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
 * 當出現當前位置分別指向s1[5],s2[3],s3[8]時導致後面無法交替下去
 */
/*    public static boolean isInterleave(String s1, String s2, String s3) {
	boolean flag = false;
	if (s3.length() != (s1.length() + s2.length())) return false;

	int len1 = s1.length();
	int len2 = s2.length();
	int len3 = s3.length();
	int p1 = 0, p2 = 0, p3 = 0;
	while ((p1 < len1 || p2 < len2) && p3 < len3) {
		if ((p1 < len1) && s3.charAt(p3) == s1.charAt(p1)) {
			p3++;
			p1++;
		} else if ((p2 < len2) && s3.charAt(p3) == s2.charAt(p2)) {
			p3++;
			p2++;
		} else {
			return false;
		}
	}
	return flag;
}*/
/**
 * 雙指標+回溯
 */
public static boolean isInterleave(String s1, String s2, String s3) {
	if (s1.length() + s2.length() != s3.length()) return false;
	return canMatch(s1, 0, s2, 0, s3, 0);
}

public static boolean canMatch(String s1, int p1, String s2, int p2, String s3, int p3) {
	if (p3 >= s3.length()) return true;

	if ((p1 < s1.length()) && (p3 < s3.length())
			&& (s1.charAt(p1) == s3.charAt(p3))
			&& (canMatch(s1, p1 + 1, s2, p2, s3, p3 + 1))) {
		System.out.println(s1.charAt(p1) +" "+s3.charAt(p3));
		return true;
	}

	if ((p2 < s2.length()) && (p3 < s3.length())
			&& (s2.charAt(p2) == s3.charAt(p3))
			&& (canMatch(s1, p1, s2, p2 + 1, s3, p3 + 1))) {
		System.out.println(s2.charAt(p2) +" "+s3.charAt(p3));
		return true;
	}
	return false;
}
/**
 * 動態規劃:二維實現方式
 * dp[i][j] = dp[i-1][j] &&s1(i)=s3(i+j) 或者dp[i][j-1] &&s2[j]=s3[i+j]
 * dp[0][0] = true
 * 時間和空間複雜度均為O(MN)
 */
public static boolean isInterleave(String s1, String s2, String s3) {
	if (s3.length() != (s1.length() + s2.length())) return false;

	int len1 = s1.length();
	int len2 = s2.length();
	// dp[i][j] 表示s1[i]和s2[j] 是否能交替組成s3[i+j]
	boolean[][] dp = new boolean[len1 + 1][len2 + 1];
	// 邊界條件為啥是true,dp[0][1]/dp[1][0]可以為true,其前提條件之一是dp[0][0]為true
	dp[0][0] = true;
	for (int i = 0; i <= len1; ++i) {
		for (int j = 0; j <= len2; ++j) {
			int p = i + j - 1;      // s3的位置
			//方式1--start,分別使用i>0 和j>0 是因為會有i>0&&j=0 或者i=0&&j>0 的情況
//                if (i > 0) {
//                    dp[i][j] = dp[i][j] || (dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(p));
//                }
//                if (j > 0) {
//                    dp[i][j] = dp[i][j] || (dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(p));
//                }
			// 方式1--end
			// 方式2--start
			if (p < 0) continue;
			// 使用這種方式會導致dp[0][0] 被修改為false,新增continue語句,可以避免這種情況
			dp[i][j] = (((i > 0) && (dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(p)))
					|| ((j > 0) && (dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(p))));
			// 方式2--end
		}
	}
	return dp[len1][len2];
}
/**
 * 動態規劃優化空間: 滾動陣列
 */
public static boolean isInterleave(String s1, String s2, String s3) {
	if (s3.length() != (s1.length() + s2.length())) return false;

	int len1 = s1.length();
	int len2 = s2.length();
	// dp[j] 表示s1[i]和s2[j] 是否能交替組成s3[i+j]
	boolean[] dp = new boolean[len2 + 1];
	// 邊界條件為啥是true,dp[1]可以為true,其前提條件之一是dp[0]為true
	dp[0] = true;
	for (int i = 0; i <= len1; ++i) {
		for (int j = 0; j <= len2; ++j) {
			int p = i + j - 1;      // s3的位置
			if (p < 0) continue;
			// 使用這種方式會導致dp[0]被修改為false,新增continue語句,可以避免這種情況
			dp[j] = (((i > 0) && (dp[j] && s1.charAt(i - 1) == s3.charAt(p)))
					|| ((j > 0) && (dp[j - 1] && s2.charAt(j - 1) == s3.charAt(p))));
		}
	}
	return dp[len2];
}
public static void main(String[] args) {
	String s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac";
	boolean ans = isInterleave(s1, s2, s3);
	System.out.println("IsInterleave demo01 result:" + ans);

	s1 = "aabcc";
	s2 = "dbbca";
	s3 = "aadbbbaccc";
	ans = isInterleave(s1, s2, s3);
	System.out.println("IsInterleave demo02 result:" + ans);
}