本文准备讲解1个算法编程问题, 这个算法编程问题来自LeetCode平台。不了解.LeetCode平台的读者可以阅读笔者文章(在线编程平台推荐-LeetCode)。问题的英文版本描述如下:
Given a string s and a string t, check if s is subsequence of t.
You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100).
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not).
问题的中文版本描述:
给定 1个 string s 和 1个 string t, 测试 s 是否为 t 的子序列。
假定 s 和 t 只包含小写英文字母字符;t 可能长度很长 (长度约为 500,000 ),s 可能长度很短 (长度少于 100 )。
子序列指 s 可以由 t 的字符构成,且 t 的字符顺序不能被改变。例如,"ace" 是 "abcde" 的子序列;"aec" 不是 "abcde" 的子序列。
Example 1:
s="abc",t="ahbgdc"
s 为 t 的子序列
Example 2:
s="axc",t="ahbgdc"
s 不为 t 的子序列
为了说明解题过程,对例子1作图如下:
从图中可以看到,首先找到 string s 的第1个字符,然后在 string t 中从头顺序寻找这个目标字符。如果没有找到目标字符,说明 s 不为 t 的子序列。如果找到目标字符,需要记录目标字符在 string t 的位置。接着找到 string s 的第2个字符,做同样的处理;直到 string s 的每个字符都被处理。这里有2个问题非常关键。第1个问题是必须以 string s 的所有字符为遍历对象,不能以 string t 的所有字符为遍历对象。回忆题目的说明:t 可能长度很长 (长度约为 500,000 ),s 可能长度很短 (长度少于 100 ),以 string t 的所有字符为遍历对象会导致处理非常缓慢,浪费大量资源。错误的程序例子如下:
第2个问题是必须记住 string t 中的搜索位置并充分利用 JAVA 提供的处理功能。以下的低效例子并无什么错误,但会比较低效:
这种低效的处理方案大约需要 45ms 的程序运行时间。最后,公布1种较好的处理方案;这种方案在 LeetCode 平台上需要 3 ms 的程序运行时间。
这里请注意 string 的 indexOf 方法,不能用单参数的 indexOf 方法; 单参数的 indexOf 方法返回的搜索位置无法应用在方案中,方案只能用双参数的 indexOf 方法。另外建议读者在读文章之前先亲手在 LeetCode 平台上做题,寻找自创的解答方案。