Tag Archives: 字符串

LeetCode Reverse String

LeetCode Reverse String Write a function that takes a string as input and returns the string reversed. Example: Given s = “hello”, return “olleh”.


本题要把一个字符串逆序一下。最简单的题了,两种方法,一种是直接调用STL的reverse函数;另一种方法是用首尾指针不断swap。 方法1代码如下: [cpp] class Solution { public: string reverseString(string s) { reverse(s.begin(), s.end()); return s; } }; [/cpp] 本代码提交AC,用时9MS。 方法2代码如下: [cpp] class Solution { public: string reverseString(string s) { int i = 0, j = s.size() – 1; while (i < j) { swap(s[i], s[j]); ++i; –j; } return s; } }; [/cpp] 本代码提交AC,用时也是9MS。]]>

LeetCode Word Pattern

290. Word Pattern

Given a pattern and a string str, find if str follows the same pattern.

Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str.

Example 1:

Input: pattern = "abba", str = "dog cat cat dog"
Output: true

Example 2:

Input:pattern = "abba", str = "dog cat cat fish"
Output: false

Example 3:

Input: pattern = "aaaa", str = "dog cat cat dog"
Output: false

Example 4:

Input: pattern = "abba", str = "dog dog dog dog"
Output: false

Notes:
You may assume pattern contains only lowercase letters, and str contains lowercase letters that may be separated by a single space.


给定一个pattern字符串和一个实例字符串str,问这个str和pattern是否是一个双射(bijection)。双射这个词很重要,这表明str要和pattern一致,pattern也要和str一致。比如题目中第四个例子,str其实是符合pattern的,因为pattern说首尾和中间两个单词需要分别相等,但是a和b一定相等吗?我们从pattern对应到str就不行了,因为str四个单词都相等,但pattern的a和b不相等。 所以我们首先把str切分成单词数组,然后构建两个unordered_map分别对应pattern到str的映射和str到pattern的映射。只有当两个映射都正确才正确。 完整代码如下:

class Solution {
public:
    bool wordPattern(string pattern, string str)
    {
        vector<string> segs;
        int s = 0;
        for (int t = 1; t <= str.size(); ++t) {
            if (t == str.size() || str[t] == ‘ ‘) {
                segs.push_back(str.substr(s, t – s));
                s = t + 1;
            }
        }
        if (pattern.size() != segs.size())
            return false;
        unordered_map<char, string> bijection1;
        unordered_map<string, char> bijection2;
        for (int i = 0; i < pattern.size(); ++i) {
            if (bijection1.find(pattern[i]) == bijection1.end()) {
                bijection1[pattern[i]] = segs[i];
            }
            else {
                if (bijection1[pattern[i]] != segs[i])
                    return false;
            }
            if (bijection2.find(segs[i]) == bijection2.end()) {
                bijection2[segs[i]] = pattern[i];
            }
            else {
                if (bijection2[segs[i]] != pattern[i])
                    return false;
            }
        }
        return true;
    }
};

本代码提交AC,用时0MS。

二刷。很简单:

class Solution {
public:
	bool wordPattern(string pattern, string str) {
		vector<string> words;
		int i = 0, j = 0, n = str.size();
		while (i < n) {
			j = i + 1;
			while (j < n&&str[j] != ' ')++j;
			string word = str.substr(i, j - i);
			words.push_back(word);
			i = j + 1;
		}
		if (pattern.size() != words.size())return false;
		int m = pattern.size();
		unordered_map<char, string> hash1;
		unordered_map<string, char> hash2;
		for (int i = 0; i < m; ++i) {
			if (hash1.find(pattern[i]) == hash1.end()) {
				hash1[pattern[i]] = words[i];
			}
			if (hash2.find(words[i]) == hash2.end()) {
				hash2[words[i]] = pattern[i];
			}

			if (hash1[pattern[i]] != words[i] || hash2[words[i]] != pattern[i])return false;
		}
		return true;
	}
};

本代码提交AC,用时0MS。

LeetCode Find the Difference

LeetCode Find the Difference Given two strings s and t which consist of only lowercase letters. String t is generated by random shuffling string s and then add one more letter at a random position. Find the letter that was added in t. Example:

Input:
s = "abcd"
t = "abcde"
Output:
e
Explanation:
'e' is the letter that was added.

有两个字符串s和t,其中t是由s shuffle而来,并且在随机位置上随机加上了一个字符,现在要找出这个随机加上的字符是哪个。 第一思路是,t由s shuffle而来的部分和s的组成是一样的,只是字符排列顺序不一样,所以每个字符出现的次数是一样的,而加上的那个字符导致该字符的出现次数在s和t中不一样,所以用一个hash就可以找到这个出现次数不一样的字符。 完整代码如下: [cpp] class Solution { public: char findTheDifference(string s, string t) { unordered_map<char, size_t> mpS, mpT; for (int i = 0; i < s.size(); i++) { mpS[s[i]]++; } for (int i = 0; i < t.size(); i++) { mpT[t[i]]++; } unordered_map<char, size_t>::iterator it = mpT.begin(); while (it != mpT.end()) { if (mpS.find((*it).first) == mpS.end() || mpS[(*it).first] != (*it).second)return (*it).first; it++; } return 0; // never reach here } }; [/cpp] 本代码提交AC,用时13MS。 后来想到之前做的一个题LeetCode Single Number,把s和t组合起来,不就相当于除了加入的字符,其他字符都重复出现了偶数次吗,所以把s和t中的所有字符异或一下,得到的结果就是那个插入的字符,真是高明。 完整代码如下: [cpp] class Solution { public: char findTheDifference(string s, string t) { char ans = 0; for (int i = 0; i < s.size(); i++) { ans ^= s[i]; } for (int i = 0; i < t.size(); i++) { ans ^= t[i]; } return ans; } }; [/cpp] 本代码提交AC,用时3MS,相当于前一个版本的零头,果然位运算的效率就是高。]]>

LeetCode Fizz Buzz

LeetCode Fizz Buzz Write a program that outputs the string representation of numbers from 1 to n. But for multiples of three it should output “Fizz” instead of the number and for the multiples of five output “Buzz”. For numbers which are multiples of both three and five output “FizzBuzz”. Example:

n = 15,
Return:
[
    "1",
    "2",
    "Fizz",
    "4",
    "Buzz",
    "Fizz",
    "7",
    "8",
    "Fizz",
    "Buzz",
    "11",
    "Fizz",
    "13",
    "14",
    "FizzBuzz"
]

从1到n生成数字字符串,但是如果某个数能整除15,则生成FizzBuzz;能整除5,则生成Buzz;能整除3则生成Fizz。 发现<string>中的to_string()很好用:-) 完整代码如下: [cpp] class Solution { public: vector<string> fizzBuzz(int n) { vector<string> ans; for (int i = 1; i <= n; i++) { if (i % 15 == 0)ans.push_back("FizzBuzz"); else if (i % 5 == 0)ans.push_back("Buzz"); else if (i % 3 == 0)ans.push_back("Fizz"); else ans.push_back(to_string(i)); } return ans; } }; [/cpp] 本代码提交AC,用时3MS。]]>

LeetCode Add Strings

num1 and num2 represented as string, return the sum of num1 and num2. Note:

  1. The length of both num1 and num2 is < 5100.
  2. Both num1 and num2 contains only digits 0-9.
  3. Both num1 and num2 does not contain any leading zero.
  4. You must not use any built-in BigInteger library or convert the inputs to integer directly.

实现字符串加法,按照小学老师教的,从低到高一位一位加,注意保留进位。这题仔细一点,然后调试两次就差不多能AC了。 代码中需要注意运算符优先级,加法优先级高于三目运算符,所以三目运算符要加括号。 完整代码如下: [cpp] class Solution { public: string addStrings(string num1, string num2) { string ans = ""; int i = num1.size() – 1, j = num2.size() – 1; bool carry = false; while (i >= 0 || j >= 0) { int sum = 0; if (i < 0)sum = (num2[j] – ‘0’) + (carry ? 1 : 0); else if (j < 0)sum = (num1[i] – ‘0’) + (carry ? 1 : 0); else sum = (num1[i] – ‘0’) + (num2[j] – ‘0’) + (carry ? 1 : 0); //注意运算符优先级,要加括号 if (sum >= 10) { carry = true; sum -= 10; } else { carry = false; } char c = ‘0’ + sum; ans = c + ans; i–; j–; } if (carry)return ‘1’ + ans; else return ans; } }; [/cpp] 本代码提交AC,用时12MS。]]>

LeetCode Number of Segments in a String

LeetCode Number of Segments in a String Count the number of segments in a string, where a segment is defined to be a contiguous sequence of non-space characters. Please note that the string does not contain any non-printable characters. Example:

Input: "Hello, my name is John"
Output: 5

统计一个字符串中segments的个数,每个segment被至少一个空格隔开,所以不能只单纯统计空格的个数。其实一个segment的特点是以非空格开头,并且前一个字符一定是空格;或者它是第一个segment,开头没有空格。 完整代码如下: [cpp] class Solution { public: int countSegments(string s) { if (s == "")return 0; int ans = 0; for (int i = 0; i < s.size(); i++) { if (s[i] != ‘ ‘) { if (i == 0 || (s[i – 1] == ‘ ‘))ans++; } } return ans; } }; [/cpp] 本代码提交AC,用时0MS。]]>

LeetCode Edit Distance

72. Edit Distance

Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.

You have the following 3 operations permitted on a word:

  1. Insert a character
  2. Delete a character
  3. Replace a character

Example 1:

Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation: 
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')

Example 2:

Input: word1 = "intention", word2 = "execution"
Output: 5
Explanation: 
intention -> inention (remove 't')
inention -> enention (replace 'i' with 'e')
enention -> exention (replace 'n' with 'x')
exention -> exection (replace 'n' with 'c')
exection -> execution (insert 'u')

本题要求两个字符串的编辑距离,很经典的一道动态规划题。 两个字符串的编辑距离是指通过插入、删除和替换这三种操作,将word1变换为word2(或者将word2变换为word1)。 编辑距离本科算法课就学过了,把word1和word2摆成一个表格的形式,然后从左往右,从上往下填表格,然后编辑距离就是表格右下角的值。 假设word1水平方向摆放,word2竖直方向摆放,令dp[row][col]表示把word2[:row]变换为word1[:col]需要的编辑距离,则这种变换可以通过三种方法获得:

  1. 删掉字符word2[row],然后把word2[:row-1]变换为word1[:col],删除代价为1,所以dp[row][col]=dp[row-1][col]+1
  2. 在word2[:row]变换为word1[:col-1]的基础上,在word2[:row]末尾插入字符word1[col],这样就把word2[:row]变为了word1[:col],插入代价为1,所以dp[row][col]=dp[row][col-1]+1
  3. 如果word1[col]==word2[row],则word2[:row]变为word1[:col]就相当于word2[:row-1]变为word1[:col-1],此时dp[row][col]=dp[row-1][col-1];如果word1[col]!=word2[row],则可以在word2[:row-1]变为word1[:col-1]的基础上,将word2[row]替换为word1[col],替换代价为1,所以dp[row][col]=dp[row-1][col-1]+1

综合以上三种情况(实际是四种情况),得到的递归公式为:
dp[row][col]=min(min(dp[row-1][col],dp[row][col-1])+1,dp[row-1][col-1]+(word1[col]==word2[row]?0:1))
完整的代码如下:

class Solution {
public:
    int minDistance(string word1, string word2)
    {
        if (word1.size() == 0 || word2.size() == 0)
            return max(word1.size(), word2.size());
        vector<vector<int> > dp(word2.size() + 1, vector<int>(word1.size() + 1, 0));
        for (int row = 1; row <= word2.size(); row++)
            dp[row][0] = row;
        for (int col = 1; col <= word1.size(); col++)
            dp[0][col] = col;
        for (int row = 1; row <= word2.size(); row++) {
            for (int col = 1; col <= word1.size(); col++) {
                dp[row][col] = min(dp[row – 1][col], dp[row][col – 1]) + 1;
                dp[row][col] = min(dp[row][col], dp[row – 1][col – 1] + (word1[col – 1] == word2[row – 1] ? 0 : 1));
            }
        }
        return dp[word2.size()][word1.size()];
    }
};

本代码提交AC,用时28MS。

DP题一般都要填表格,很多情况下,填第row行表格可能只需要利用第row-1行的信息,所以可以只保留两行的结果,用于缩减空间复杂度。下面这种实现只利用了额外的2*min(row,col)空间:

class Solution {
public:
    int minDistance(string word1, string word2)
    {
        if (word2.size() < word1.size()) {
            swap(word1, word2);
        }
        if (word1.size() == 0)
            return word2.size();
        vector<int> dp1(word1.size() + 1, 0), dp2(word1.size() + 1, 0);
        for (int col = 1; col <= word1.size(); col++)
            dp1[col] = col;
        for (int row = 1; row <= word2.size(); row++) {
            dp1[0] = row – 1; // caution
            dp2[0] = row; // caution
            for (int col = 1; col <= word1.size(); col++) {
                dp2[col] = min(dp1[col], dp2[col – 1]) + 1;
                dp2[col] = min(dp2[col], dp1[col – 1] + (word1[col – 1] == word2[row – 1] ? 0 : 1));
            }
            swap(dp1, dp2);
        }
        return dp1[word1.size()];
    }
};

本代码提交AC,用时19MS,确实要比之前的快一点。

LeetCode Restore IP Addresses

93. Restore IP Addresses

Given a string containing only digits, restore it by returning all possible valid IP address combinations.

Example:

Input: "25525511135"
Output: ["255.255.11.135", "255.255.111.35"]

本题需要给一个数字字符串添加点号,使其成为一个合法的IP地址。
递归求解。首先设置两个数组kMinLen和kMaxLen,表示剩余字符串的最小/大长度,比如开始时step=0,则字符串的长度范围应该是[4,12]。

const vector<int> kMinLen = { 4, 3, 2, 1 };
const vector<int> kMaxLen = { 12, 9, 6, 3 };

然后递归的切当前字符串最多前3个字符,转成int,看是否<=255,如果是,则继续递归。直到step==4且没有剩余字符时,得到一个合法的IP地址。

完整代码如下:

const vector<int> kMinLen = { 4, 3, 2, 1 };
const vector<int> kMaxLen = { 12, 9, 6, 3 };
class Solution {
public:
    void work(vector<string>& ans, string cand, string left, int step)
    {
        if (step == 4) {
            if (left.size() == 0) {
                ans.push_back(cand);
            }
            return;
        }
        if (left.size() >= kMinLen[step] && left.size() <= kMaxLen[step]) {
            int border = min(3, int(left.size()));
            for (int l = 1; l <= border; l++) {
                string part_str = left.substr(0, l);
                if (part_str != "0" && part_str[0] == ‘0’)
                    continue; // 防止"010"这样的leading zero
                int part_int = atoi(part_str.c_str());
                if (part_int <= 255) {
                    string tmp = cand + left.substr(0, l);
                    if (step < 3)
                        tmp += ".";
                    work(ans, tmp, left.substr(l), step + 1);
                }
            }
        }
    }
    vector<string> restoreIpAddresses(string s)
    {
        vector<string> ans;
        string cand = "";
        work(ans, cand, s, 0);
        return ans;
    }
};

本代码提交AC,用时3MS。

二刷。使用数组保存ip地址更方便,代码如下:

class Solution {
public:
	void dfs(vector<string>& ans,vector<string>& cand, string &s, int idx) {
		if (cand.size() == 4 && idx == s.size()) {
			string ip = "";
			for (int i = 0; i < cand.size(); ++i) {
				ip = ip + cand[i] + ".";
			}
			ans.push_back(ip.substr(0, ip.size() - 1));
			return;
		}
		if (cand.size() == 4 && idx < s.size())return;
		if (cand.size() < 4 && idx >= s.size())return;
		for (int i = idx; i < s.size() && i < idx + 3; ++i) {
			string part = s.substr(idx, i - idx + 1);
			if (part[0] == '0'&&part.size() > 1)continue;
			int val = stoi(part);
			if (val <= 255) {
				cand.push_back(part);
				dfs(ans, cand, s, i + 1);
				cand.pop_back();
			}
		}
	}
	vector<string> restoreIpAddresses(string s) {
		vector<string> ans;
		vector<string> cand;
		dfs(ans, cand, s, 0);
		return ans;
	}
};

本代码提交AC,用时0MS。

LeetCode Simplify Path

71. Simplify Path

Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path.

In a UNIX-style file system, a period . refers to the current directory. Furthermore, a double period .. moves the directory up a level.

Note that the returned canonical path must always begin with a slash /, and there must be only a single slash / between two directory names. The last directory name (if it exists) must not end with a trailing /. Also, the canonical path must be the shortest string representing the absolute path.

Example 1:

Input: "/home/"
Output: "/home"
Explanation: Note that there is no trailing slash after the last directory name.

Example 2:

Input: "/../"
Output: "/"
Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go.

Example 3:

Input: "/home//foo/"
Output: "/home/foo"
Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one.

Example 4:

Input: "/a/./b/../../c/"
Output: "/c"

Example 5:

Input: "/a/../../b/../c//.//"
Output: "/c"

Example 6:

Input: "/a//b////c/d//././/.."
Output: "/a/b/c"

简化Unix路径字符串。使用栈数据结构,扫描字符串,获取/之前的字符串,如果是一点.则保持当前路径,什么也不做;如果是两点..则弹栈,否则把字符串压栈。 需要注意的是/../,/.,/…等情况,三个点应该认为一个合法的路径字符串,虽然在Windows上并不合法。所以我们在进行算法之前,不管原始字符串末尾是否包含/,我们都在末尾添加上斜杠/,以便后续统一处理。 扫描完一次字符串之后,把栈内字符串依次弹出并组合成一个简化的路径。 完整代码如下:

class Solution {
public:
    string simplifyPath(string path)
    {
        path += "/";
        stack<string> sPath;
        string p1 = "";
        for (int i = 0; i < path.size(); i++) {
            if (path[i] == ‘/’) {
                if (p1 == "" || p1 == ".") {
                }
                else if (p1 == "..") {
                    if (!sPath.empty())
                        sPath.pop();
                }
                else {
                    sPath.push(p1);
                }
                p1 = "";
            }
            else
                p1 += path[i];
        }
        if (sPath.empty())
            return "/";
        string ans = "";
        while (!sPath.empty()) {
            ans = "/" + sPath.top() + ans;
            sPath.pop();
        }
        return ans;
    }
};

本代码提交AC,用时6MS。

二刷。更简洁代码:

class Solution {
public:
	string simplifyPath(string path) {
		stack<string> stk;
		int n = path.size();
		int i = 0, j = 0;
		while (i < n) {
			while (i < n&&path[i] == '/')++i;
			if (i >= n)break;
			j = i + 1;
			while (j < n&&path[j] != '/')++j;
			string name = path.substr(i, j - i);
			if (name == ".." && !stk.empty())stk.pop();
			if (name != "."&&name != "..")stk.push(name);
			i = j;
		}
		string ans = "";
		while (!stk.empty()) {
			ans = "/" + stk.top() + ans;
			stk.pop();
		}
		if (ans == "")return "/";
		else return ans;
	}
};

本代码提交AC,用时8MS。

LeetCode Multiply Strings

43. Multiply Strings

Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string.

Example 1:

Input: num1 = "2", num2 = "3"
Output: "6"

Example 2:

Input: num1 = "123", num2 = "456"
Output: "56088"

Note:

  1. The length of both num1 and num2 is < 110.
  2. Both num1 and num2 contain only digits 0-9.
  3. Both num1 and num2 do not contain any leading zero, except the number 0 itself.
  4. You must not use any built-in BigInteger library or convert the inputs to integer directly.

把两个以字符串形式存储的非负整数相乘起来,输出字符串结果。很考验基本功的一个题目,使用小学学过的乘法来做,一位一位相乘,然后把每一位相乘的结果加起来得到最终结果。 比如35*423,先调个位置423*35,确保num2长度短于num1,然后我们循环num2的每一位,比如首先5*423=2115,然后3*423=1269,但是加起来的时候要注意,1269要往前缩进一位成12690。最终结果为2115+12690=14805。 所以整个过程需要实现两个辅助函数,两个字符串相加,以及一个字符和字符串相乘的函数。完整代码如下:

class Solution {
public:
    string add(string num1, string num2)
    {
        int i = num1.size() – 1, j = num2.size() – 1;
        string ans = "";
        bool carry = false;
        while (i >= 0 || j >= 0) {
            int sum = (i >= 0 ? (num1[i] – ‘0’) : 0) + (j >= 0 ? (num2[j] – ‘0’) : 0);
            sum += carry ? 1 : 0;
            if (sum >= 10) {
                ans.push_back(sum – 10 + ‘0’);
                carry = true;
            }
            else {
                ans.push_back(sum + ‘0’);
                carry = false;
            }
            i–;
            j–;
        }
        if (carry)
            ans.push_back(‘1’);
        reverse(ans.begin(), ans.end());
        return ans;
    }
    string multiply(string num1, char c)
    {
        if (c == ‘0’)
            return "0";
        if (c == ‘1’)
            return num1;
        string ans = "";
        int i = num1.size() – 1;
        int carry = 0;
        while (i >= 0) {
            int prod = (num1[i] – ‘0’) * (c – ‘0’);
            prod += carry;
            if (prod >= 10) {
                ans.push_back(prod % 10 + ‘0’);
                carry = prod / 10;
            }
            else {
                ans.push_back(prod + ‘0’);
                carry = 0;
            }
            i–;
        }
        if (carry > 0)
            ans.push_back(carry + ‘0’);
        reverse(ans.begin(), ans.end());
        return ans;
    }
    string multiply(string num1, string num2)
    {
        if (num1.size() < num2.size()) { // 确保num1长于num2 string tmp = num2; num2 = num1; num1 = tmp; } string ans = "0"; int j = num2.size() – 1, k = 0; // k:缩进的位数 while (j >= 0) { string p = multiply(num1, num2[j]); for (int i = 0; i < k; i++) p.push_back(‘0’); ans = add(ans, p); j–; k++; } return ans; } };

本代码提交AC,用时26MS。

二刷。上述解法不够简洁,讨论区有一种很漂亮的解法:https://discuss.leetcode.com/topic/30508/easiest-java-solution-with-graph-explanation/60,图片解释如下:

也就是可以算出来两个digit相乘的结果在最终结果中的下标位置,比如上图中123*45,num1的2乘以num2的4的结果是8,对应的下标分别是num1的i=1和num2的j=0,两个digit相乘结果最多可以占两位,这两位在最终结果中的下标是i+j和i+j+1,这个例子就是i+j=1,j+j+1=2,相乘结果08正好叠加在最终结果的第1和2位。
完整代码如下:

class Solution {
public:
    string multiply(string num1, string num2)
    {
        int n1 = num1.size(), n2 = num2.size();
        vector<int> ans(n1 + n2, 0);
        for (int i = n1 – 1; i >= 0; –i) {
            for (int j = n2 – 1; j >= 0; –j) {
                int mul = (num1[i] – ‘0’) * (num2[j] – ‘0’);
                int p1 = i + j, p2 = i + j + 1;
                int sum = mul + ans[p2];
                ans[p1] += sum / 10;
                ans[p2] = sum % 10;
            }
        }
        string ret = "";
        int i = 0;
        while (i < n1 + n2 && ans[i] == 0)
            ++i;
        if (i >= n1 + n2)
            return "0";
        while (i < n1 + n2) {
            ret.push_back(‘0’ + ans[i]);
            ++i;
        }
        return ret;
    }
};

本代码提交AC,用时9MS。

三刷。巧妙方法还是没记住,下面依然是小学生解法,只不过代码好看一点。

class Solution {
public:
	string SingleMultiply(string s, char c) {
		string ans = "";
		int vc = c - '0';
		int carry = 0;
		for (int i = s.size() - 1; i >= 0; --i) {
			int vs = s[i] - '0';
			int prod = vc * vs + carry;
			ans.push_back('0' + (prod % 10));
			carry = prod / 10;
		}
		if (carry > 0)ans.push_back(carry + '0');
		return ans;
	}
	string multiply(string num1, string num2) {
		int n1 = num1.size(), n2 = num2.size();
		if (n1 > n2)return multiply(num2, num1);
		if (num1 == "0")return "0";
		vector<string> prods;
		int max_len = 0;
		for (int i = n1 - 1; i >= 0; --i) {
			string prod = string(n1 - i - 1, '0') + SingleMultiply(num2, num1[i]);
			max_len = prod.size() > max_len ? prod.size() : max_len;
			prods.push_back(prod);
		}
		string ans = "";
		int carry = 0;
		for (int i = 0; i < max_len; ++i) {
			int val = 0;
			for (int j = 0; j < prods.size(); ++j) {
				if (i < prods[j].size())val += (prods[j][i] - '0');
			}
			val += carry;
			ans.push_back('0' + (val % 10));
			carry = val / 10;
		}
		if (carry > 0)ans.push_back('0' + carry);
		reverse(ans.begin(), ans.end());
		return ans;
	}
};

本代码提交AC,用时24MS。