https://leetcode.com/problems/is-subsequence/
Given a string s and a string t, check if s is subsequence of t.
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).
Follow up: If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?
Credits: Special thanks to @pbrother for adding this problem and creating all test cases.
Example 1:
Input: s = "abc", t = "ahbgdc" Output: true Example 2:
Input: s = "axc", t = "ahbgdc" Output: false
Constraints:
0 <= s.length <= 100 0 <= t.length <= 10^4 Both strings consists only of lowercase characters.
Please review for performance.
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace RecurssionQuestions
{
/// <summary>
/// https://leetcode.com/problems/is-subsequence/
/// </summary>
[TestClass]
public class IsSubsequenceTest
{
[TestMethod]
public void TestMethod1()
{
string s = "abc", t = "ahbgdc";
Assert.IsTrue(IsSubsequence(s, t));
Assert.IsTrue(IsSubsequence2(s, t));
}
[TestMethod]
public void TestMethod2()
{
string s = "axc", t = "ahbgdc";
Assert.IsFalse(IsSubsequence(s, t));
Assert.IsFalse(IsSubsequence2(s, t));
}
public bool IsSubsequence(string s, string t)
{
return Helper(s, t, 0, 0);
}
/// <summary>
/// if the letters are equal (letter is found) continue to the next letter of s
/// if the letter is not found in t continue to the next letter of t.
/// if you reached the end of s, then s is a subsequence of t.
/// if you reach the end of t. then s is not a subsequence of t
/// </summary>
/// <param name="s"></param>
/// <param name="t"></param>
/// <param name="sIndex"></param>
/// <param name="tIndex"></param>
/// <returns></returns>
private bool Helper(string s, string t, int sIndex, int tIndex)
{
if (sIndex == s.Length)
{
return true;
}
if (tIndex == t.Length)
{
return false;
}
if (s[sIndex] == t[tIndex])
{
return Helper(s, t, sIndex + 1, tIndex + 1);
}
else
{
return Helper(s, t, sIndex, tIndex + 1);
}
}
public bool IsSubsequence2(string s, string t)
{
if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(t))
{
return false;
}
Dictionary<char, List<int>> map = new Dictionary<char, List<int>>();
//pre-process t
for (int i = 0; i < t.Length; i++)
{
if (!map.ContainsKey(t[i]))
{
map.Add(t[i], new List<int>());
}
map[t[i]].Add(i);
}
int prev = -1;
for (int i = 0; i < s.Length; i++)
{
if (!map.ContainsKey(s[i]))
{
return false;
}
else
{
var list = map[s[i]];
prev = BinarySearch(prev, list, 0, list.Count - 1);
if (prev == -1)
{
return false;
}
prev++;
}
}
return true;
}
private int BinarySearch(int prev, List<int> list, int start, int end)
{
while (start <= end)
{
int mid = (end - start) / 2 + start;
if (list[mid] < prev)
{
start = mid + 1;
}
else
{
end = mid - 1;
}
}
if (start == list.Count)
{
return -1;
}
return list[start];
}
}
}