校招算法笔面试 | 校招笔面试真题-字符混编

题目

题目链接

解题思路

这是一个字符串混编问题,可以使用动态规划求解。关键点:

  1. 动态规划定义

    • d p [ i ] [ j ] dp[i][j] dp[i][j] 表示 A A A 的前 i i i 个字符和 B B B 的前 j j j 个字符能否混编成 C C C 的前 i + j i+j i+j 个字符
    • i i i 表示使用了 A A A 的前 i i i 个字符
    • j j j 表示使用了 B B B 的前 j j j 个字符
  2. 状态转移

    • 如果当前字符来自 A A A d p [ i ] [ j ] = d p [ i − 1 ] [ j ] ∧ A [ i − 1 ] = C [ i + j − 1 ] dp[i][j] = dp[i-1][j] \land A[i-1] = C[i+j-1] dp[i][j]=dp[i1][j]A[i1]=C[i+j1]
    • 如果当前字符来自 B B B d p [ i ] [ j ] = d p [ i ] [ j − 1 ] ∧ B [ j − 1 ] = C [ i + j − 1 ] dp[i][j] = dp[i][j-1] \land B[j-1] = C[i+j-1] dp[i][j]=dp[i][j1]B[j1]=C[i+j1]
  3. 基本判断

    • 长度必须匹配: n + m = v n + m = v n+m=v
    • 初始状态: d p [ 0 ] [ 0 ] = t r u e dp[0][0] = true dp[0][0]=true

代码

class Mixture {
public:
    bool chkMixture(string A, int n, string B, int m, string C, int v) {
        if(n + m != v) return false;
        
        vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, false));
        dp[0][0] = true;
        
        // 只使用A串
        for(int i = 1; i <= n; i++) {
            dp[i][0] = dp[i-1][0] && (A[i-1] == C[i-1]);
        }
        
        // 只使用B串
        for(int j = 1; j <= m; j++) {
            dp[0][j] = dp[0][j-1] && (B[j-1] == C[j-1]);
        }
        
        // 动态规划填表
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                // 当前字符可以来自A或B
                dp[i][j] = (dp[i-1][j] && A[i-1] == C[i+j-1]) || 
                          (dp[i][j-1] && B[j-1] == C[i+j-1]);
            }
        }
        
        return dp[n][m];
    }
};
import java.util.*;

public class Mixture {
    public boolean chkMixture(String A, int n, String B, int m, String C, int v) {
        if(n + m != v) return false;
        
        boolean[][] dp = new boolean[n + 1][m + 1];
        dp[0][0] = true;
        
        // 只使用A串
        for(int i = 1; i <= n; i++) {
            dp[i][0] = dp[i-1][0] && (A.charAt(i-1) == C.charAt(i-1));
        }
        
        // 只使用B串
        for(int j = 1; j <= m; j++) {
            dp[0][j] = dp[0][j-1] && (B.charAt(j-1) == C.charAt(j-1));
        }
        
        // 动态规划填表
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                // 当前字符可以来自A或B
                dp[i][j] = (dp[i-1][j] && A.charAt(i-1) == C.charAt(i+j-1)) || 
                          (dp[i][j-1] && B.charAt(j-1) == C.charAt(i+j-1));
            }
        }
        
        return dp[n][m];
    }
}
# -*- coding:utf-8 -*-

class Mixture:
    def chkMixture(self, A, n, B, m, C, v):
        if n + m != v:
            return False
            
        dp = [[False] * (m + 1) for _ in range(n + 1)]
        dp[0][0] = True
        
        # Only use string A
        for i in range(1, n + 1):
            dp[i][0] = dp[i-1][0] and (A[i-1] == C[i-1])
        
        # Only use string B
        for j in range(1, m + 1):
            dp[0][j] = dp[0][j-1] and (B[j-1] == C[j-1])
        
        # Fill dp table
        for i in range(1, n + 1):
            for j in range(1, m + 1):
                # Current char can come from either A or B
                dp[i][j] = (dp[i-1][j] and A[i-1] == C[i+j-1]) or \
                          (dp[i][j-1] and B[j-1] == C[i+j-1])
        
        return dp[n][m]

算法及复杂度

  • 算法:动态规划
  • 时间复杂度: O ( n m ) \mathcal{O}(nm) O(nm),需要填充整个 d p dp dp
  • 空间复杂度: O ( n m ) \mathcal{O}(nm) O(nm),需要二维 d p dp dp 数组
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值