Longest common subsequence solution
$begingroup$
I've seen this today on a mock interview and wanted to give it a try. I'd love to hear some feedback from you guys. This is my second attempt at the problem, initially I had a mess of if
/else
towers and nested loops.
/*
* Write a function that takes two strings s1 and s2 and returns the
* longest common subsequences of s1 and s2.
*
* Examples:
* s1: ABAZDC s2: BACBAD result: ABAD
* s1: AGGTAB s2: GXTXAYB result: GTAB
* s1: aaaa s2: aa result: aa
* s1: aaaa s2: '' result: ''
*/
public class LongestSubsequence {
public static void main(String args) {
LongestSubsequence ls = new LongestSubsequence();
assertEquals("ABAD", ls.solve("ABAZDC", "BACBAD"));
assertEquals("GTAB", ls.solve("AGGTAB", "GXTXAYB"));
assertEquals("aa", ls.solve("aaaa", "aa"));
assertEquals("", ls.solve("aaaa", ""));
assertEquals("ABAD", ls.solve("BACBAD", "ABAZDC"));
assertEquals("aaaa", ls.solve("bcaaaa", "aaaabc"));
assertEquals("aaaa", ls.solve("bcaaaade", "deaaaabc"));
}
private String solve(String s1, String s2) {
if (s1.length() == 0 || s2.length() == 0) {
return "";
}
String subSeq1 = getLongestSubsequence(s1, s2);
String subSeq2 = getLongestSubsequence(s2, s1);
return (subSeq1.length() >= subSeq2.length() ? subSeq1 : subSeq2);
}
private String getLongestSubsequence(String first, String second) {
String retValue = "";
int currentIndex = 0;
for (int remaining = first.length(); retValue.length() < remaining; remaining--) {
StringBuilder firstWorker = new StringBuilder(first.substring(currentIndex));
StringBuilder secondWorker = new StringBuilder(second);
StringBuilder possibleSequence = new StringBuilder();
while (firstWorker.length() > 0 && secondWorker.length() > 0) {
String ch = firstWorker.substring(0, 1);
int firstIndex = secondWorker.indexOf(ch);
if (firstIndex != -1) {
possibleSequence.append(ch);
secondWorker.delete(0, firstIndex + 1);
}
firstWorker.delete(0, 1);
}
if (possibleSequence.length() > retValue.length()) {
retValue = possibleSequence.toString();
}
currentIndex++;
}
return retValue;
}
}
java interview-questions dynamic-programming
$endgroup$
add a comment |
$begingroup$
I've seen this today on a mock interview and wanted to give it a try. I'd love to hear some feedback from you guys. This is my second attempt at the problem, initially I had a mess of if
/else
towers and nested loops.
/*
* Write a function that takes two strings s1 and s2 and returns the
* longest common subsequences of s1 and s2.
*
* Examples:
* s1: ABAZDC s2: BACBAD result: ABAD
* s1: AGGTAB s2: GXTXAYB result: GTAB
* s1: aaaa s2: aa result: aa
* s1: aaaa s2: '' result: ''
*/
public class LongestSubsequence {
public static void main(String args) {
LongestSubsequence ls = new LongestSubsequence();
assertEquals("ABAD", ls.solve("ABAZDC", "BACBAD"));
assertEquals("GTAB", ls.solve("AGGTAB", "GXTXAYB"));
assertEquals("aa", ls.solve("aaaa", "aa"));
assertEquals("", ls.solve("aaaa", ""));
assertEquals("ABAD", ls.solve("BACBAD", "ABAZDC"));
assertEquals("aaaa", ls.solve("bcaaaa", "aaaabc"));
assertEquals("aaaa", ls.solve("bcaaaade", "deaaaabc"));
}
private String solve(String s1, String s2) {
if (s1.length() == 0 || s2.length() == 0) {
return "";
}
String subSeq1 = getLongestSubsequence(s1, s2);
String subSeq2 = getLongestSubsequence(s2, s1);
return (subSeq1.length() >= subSeq2.length() ? subSeq1 : subSeq2);
}
private String getLongestSubsequence(String first, String second) {
String retValue = "";
int currentIndex = 0;
for (int remaining = first.length(); retValue.length() < remaining; remaining--) {
StringBuilder firstWorker = new StringBuilder(first.substring(currentIndex));
StringBuilder secondWorker = new StringBuilder(second);
StringBuilder possibleSequence = new StringBuilder();
while (firstWorker.length() > 0 && secondWorker.length() > 0) {
String ch = firstWorker.substring(0, 1);
int firstIndex = secondWorker.indexOf(ch);
if (firstIndex != -1) {
possibleSequence.append(ch);
secondWorker.delete(0, firstIndex + 1);
}
firstWorker.delete(0, 1);
}
if (possibleSequence.length() > retValue.length()) {
retValue = possibleSequence.toString();
}
currentIndex++;
}
return retValue;
}
}
java interview-questions dynamic-programming
$endgroup$
$begingroup$
Thank you very much, I have checked that discussion and added a few test cases to the code. It's now passing those as well. The solution became a bit more complex as I can now see that O(n) does not seem possible in this case.
$endgroup$
– fpezzini
11 hours ago
$begingroup$
I'm now trying in both directions s1 -> s2 and s2 -> s1. I'm also using string builders for efficiency, and deleting chars on s1 as well. The for loop ensures it does not try to find a solution when there are fewer characters than the current solution.
$endgroup$
– fpezzini
11 hours ago
add a comment |
$begingroup$
I've seen this today on a mock interview and wanted to give it a try. I'd love to hear some feedback from you guys. This is my second attempt at the problem, initially I had a mess of if
/else
towers and nested loops.
/*
* Write a function that takes two strings s1 and s2 and returns the
* longest common subsequences of s1 and s2.
*
* Examples:
* s1: ABAZDC s2: BACBAD result: ABAD
* s1: AGGTAB s2: GXTXAYB result: GTAB
* s1: aaaa s2: aa result: aa
* s1: aaaa s2: '' result: ''
*/
public class LongestSubsequence {
public static void main(String args) {
LongestSubsequence ls = new LongestSubsequence();
assertEquals("ABAD", ls.solve("ABAZDC", "BACBAD"));
assertEquals("GTAB", ls.solve("AGGTAB", "GXTXAYB"));
assertEquals("aa", ls.solve("aaaa", "aa"));
assertEquals("", ls.solve("aaaa", ""));
assertEquals("ABAD", ls.solve("BACBAD", "ABAZDC"));
assertEquals("aaaa", ls.solve("bcaaaa", "aaaabc"));
assertEquals("aaaa", ls.solve("bcaaaade", "deaaaabc"));
}
private String solve(String s1, String s2) {
if (s1.length() == 0 || s2.length() == 0) {
return "";
}
String subSeq1 = getLongestSubsequence(s1, s2);
String subSeq2 = getLongestSubsequence(s2, s1);
return (subSeq1.length() >= subSeq2.length() ? subSeq1 : subSeq2);
}
private String getLongestSubsequence(String first, String second) {
String retValue = "";
int currentIndex = 0;
for (int remaining = first.length(); retValue.length() < remaining; remaining--) {
StringBuilder firstWorker = new StringBuilder(first.substring(currentIndex));
StringBuilder secondWorker = new StringBuilder(second);
StringBuilder possibleSequence = new StringBuilder();
while (firstWorker.length() > 0 && secondWorker.length() > 0) {
String ch = firstWorker.substring(0, 1);
int firstIndex = secondWorker.indexOf(ch);
if (firstIndex != -1) {
possibleSequence.append(ch);
secondWorker.delete(0, firstIndex + 1);
}
firstWorker.delete(0, 1);
}
if (possibleSequence.length() > retValue.length()) {
retValue = possibleSequence.toString();
}
currentIndex++;
}
return retValue;
}
}
java interview-questions dynamic-programming
$endgroup$
I've seen this today on a mock interview and wanted to give it a try. I'd love to hear some feedback from you guys. This is my second attempt at the problem, initially I had a mess of if
/else
towers and nested loops.
/*
* Write a function that takes two strings s1 and s2 and returns the
* longest common subsequences of s1 and s2.
*
* Examples:
* s1: ABAZDC s2: BACBAD result: ABAD
* s1: AGGTAB s2: GXTXAYB result: GTAB
* s1: aaaa s2: aa result: aa
* s1: aaaa s2: '' result: ''
*/
public class LongestSubsequence {
public static void main(String args) {
LongestSubsequence ls = new LongestSubsequence();
assertEquals("ABAD", ls.solve("ABAZDC", "BACBAD"));
assertEquals("GTAB", ls.solve("AGGTAB", "GXTXAYB"));
assertEquals("aa", ls.solve("aaaa", "aa"));
assertEquals("", ls.solve("aaaa", ""));
assertEquals("ABAD", ls.solve("BACBAD", "ABAZDC"));
assertEquals("aaaa", ls.solve("bcaaaa", "aaaabc"));
assertEquals("aaaa", ls.solve("bcaaaade", "deaaaabc"));
}
private String solve(String s1, String s2) {
if (s1.length() == 0 || s2.length() == 0) {
return "";
}
String subSeq1 = getLongestSubsequence(s1, s2);
String subSeq2 = getLongestSubsequence(s2, s1);
return (subSeq1.length() >= subSeq2.length() ? subSeq1 : subSeq2);
}
private String getLongestSubsequence(String first, String second) {
String retValue = "";
int currentIndex = 0;
for (int remaining = first.length(); retValue.length() < remaining; remaining--) {
StringBuilder firstWorker = new StringBuilder(first.substring(currentIndex));
StringBuilder secondWorker = new StringBuilder(second);
StringBuilder possibleSequence = new StringBuilder();
while (firstWorker.length() > 0 && secondWorker.length() > 0) {
String ch = firstWorker.substring(0, 1);
int firstIndex = secondWorker.indexOf(ch);
if (firstIndex != -1) {
possibleSequence.append(ch);
secondWorker.delete(0, firstIndex + 1);
}
firstWorker.delete(0, 1);
}
if (possibleSequence.length() > retValue.length()) {
retValue = possibleSequence.toString();
}
currentIndex++;
}
return retValue;
}
}
java interview-questions dynamic-programming
java interview-questions dynamic-programming
edited 15 mins ago
Jamal♦
30.3k11119227
30.3k11119227
asked 13 hours ago
fpezzinifpezzini
816
816
$begingroup$
Thank you very much, I have checked that discussion and added a few test cases to the code. It's now passing those as well. The solution became a bit more complex as I can now see that O(n) does not seem possible in this case.
$endgroup$
– fpezzini
11 hours ago
$begingroup$
I'm now trying in both directions s1 -> s2 and s2 -> s1. I'm also using string builders for efficiency, and deleting chars on s1 as well. The for loop ensures it does not try to find a solution when there are fewer characters than the current solution.
$endgroup$
– fpezzini
11 hours ago
add a comment |
$begingroup$
Thank you very much, I have checked that discussion and added a few test cases to the code. It's now passing those as well. The solution became a bit more complex as I can now see that O(n) does not seem possible in this case.
$endgroup$
– fpezzini
11 hours ago
$begingroup$
I'm now trying in both directions s1 -> s2 and s2 -> s1. I'm also using string builders for efficiency, and deleting chars on s1 as well. The for loop ensures it does not try to find a solution when there are fewer characters than the current solution.
$endgroup$
– fpezzini
11 hours ago
$begingroup$
Thank you very much, I have checked that discussion and added a few test cases to the code. It's now passing those as well. The solution became a bit more complex as I can now see that O(n) does not seem possible in this case.
$endgroup$
– fpezzini
11 hours ago
$begingroup$
Thank you very much, I have checked that discussion and added a few test cases to the code. It's now passing those as well. The solution became a bit more complex as I can now see that O(n) does not seem possible in this case.
$endgroup$
– fpezzini
11 hours ago
$begingroup$
I'm now trying in both directions s1 -> s2 and s2 -> s1. I'm also using string builders for efficiency, and deleting chars on s1 as well. The for loop ensures it does not try to find a solution when there are fewer characters than the current solution.
$endgroup$
– fpezzini
11 hours ago
$begingroup$
I'm now trying in both directions s1 -> s2 and s2 -> s1. I'm also using string builders for efficiency, and deleting chars on s1 as well. The for loop ensures it does not try to find a solution when there are fewer characters than the current solution.
$endgroup$
– fpezzini
11 hours ago
add a comment |
2 Answers
2
active
oldest
votes
$begingroup$
Bug
Your program fails on this test:
ls.solve("abddc", "acddb");
Your program finds "ab"
and "ac"
as the longest subsequences, but the actual answer should be "add"
.
The problem is that your algorithm is greedy, and it will always use any match, even if the match skips over a part that would produce a better answer. In my test case, the b
in the first string matches the b
at the end of the second string, thereby skipping over the dd
in the middle.
$endgroup$
add a comment |
$begingroup$
The method name solve
does not describe what the method is doing. There should be a method public static String longestCommonSubsequence(String a, String b)
, and the class containing that method should be called StringUtils
.
After making the method static
, there's no reason to call new LongestSubsequence
any longer since that object doesn't provide anything useful.
The variable name ch
is usually used for characters, not for strings. It creates unnecessary confusion here.
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214256%2flongest-common-subsequence-solution%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Bug
Your program fails on this test:
ls.solve("abddc", "acddb");
Your program finds "ab"
and "ac"
as the longest subsequences, but the actual answer should be "add"
.
The problem is that your algorithm is greedy, and it will always use any match, even if the match skips over a part that would produce a better answer. In my test case, the b
in the first string matches the b
at the end of the second string, thereby skipping over the dd
in the middle.
$endgroup$
add a comment |
$begingroup$
Bug
Your program fails on this test:
ls.solve("abddc", "acddb");
Your program finds "ab"
and "ac"
as the longest subsequences, but the actual answer should be "add"
.
The problem is that your algorithm is greedy, and it will always use any match, even if the match skips over a part that would produce a better answer. In my test case, the b
in the first string matches the b
at the end of the second string, thereby skipping over the dd
in the middle.
$endgroup$
add a comment |
$begingroup$
Bug
Your program fails on this test:
ls.solve("abddc", "acddb");
Your program finds "ab"
and "ac"
as the longest subsequences, but the actual answer should be "add"
.
The problem is that your algorithm is greedy, and it will always use any match, even if the match skips over a part that would produce a better answer. In my test case, the b
in the first string matches the b
at the end of the second string, thereby skipping over the dd
in the middle.
$endgroup$
Bug
Your program fails on this test:
ls.solve("abddc", "acddb");
Your program finds "ab"
and "ac"
as the longest subsequences, but the actual answer should be "add"
.
The problem is that your algorithm is greedy, and it will always use any match, even if the match skips over a part that would produce a better answer. In my test case, the b
in the first string matches the b
at the end of the second string, thereby skipping over the dd
in the middle.
answered 3 hours ago
JS1JS1
27.4k32976
27.4k32976
add a comment |
add a comment |
$begingroup$
The method name solve
does not describe what the method is doing. There should be a method public static String longestCommonSubsequence(String a, String b)
, and the class containing that method should be called StringUtils
.
After making the method static
, there's no reason to call new LongestSubsequence
any longer since that object doesn't provide anything useful.
The variable name ch
is usually used for characters, not for strings. It creates unnecessary confusion here.
$endgroup$
add a comment |
$begingroup$
The method name solve
does not describe what the method is doing. There should be a method public static String longestCommonSubsequence(String a, String b)
, and the class containing that method should be called StringUtils
.
After making the method static
, there's no reason to call new LongestSubsequence
any longer since that object doesn't provide anything useful.
The variable name ch
is usually used for characters, not for strings. It creates unnecessary confusion here.
$endgroup$
add a comment |
$begingroup$
The method name solve
does not describe what the method is doing. There should be a method public static String longestCommonSubsequence(String a, String b)
, and the class containing that method should be called StringUtils
.
After making the method static
, there's no reason to call new LongestSubsequence
any longer since that object doesn't provide anything useful.
The variable name ch
is usually used for characters, not for strings. It creates unnecessary confusion here.
$endgroup$
The method name solve
does not describe what the method is doing. There should be a method public static String longestCommonSubsequence(String a, String b)
, and the class containing that method should be called StringUtils
.
After making the method static
, there's no reason to call new LongestSubsequence
any longer since that object doesn't provide anything useful.
The variable name ch
is usually used for characters, not for strings. It creates unnecessary confusion here.
answered 3 hours ago
Roland IlligRoland Illig
11.2k11844
11.2k11844
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214256%2flongest-common-subsequence-solution%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Thank you very much, I have checked that discussion and added a few test cases to the code. It's now passing those as well. The solution became a bit more complex as I can now see that O(n) does not seem possible in this case.
$endgroup$
– fpezzini
11 hours ago
$begingroup$
I'm now trying in both directions s1 -> s2 and s2 -> s1. I'm also using string builders for efficiency, and deleting chars on s1 as well. The for loop ensures it does not try to find a solution when there are fewer characters than the current solution.
$endgroup$
– fpezzini
11 hours ago