Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 585878f

Browse files
Add one more solution for StringTransformation task
1 parent ab1fcb5 commit 585878f

File tree

3 files changed

+67
-16
lines changed

3 files changed

+67
-16
lines changed

‎interview-materials/tasks.md‎

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,6 @@ Add operation with pets batch update (for example, add new field - owner).
1919
Propose algorithm for sorting a bunch of long strings situated on disk.
2020
We have restriction of RAM size: so only one string could be loaded into RAM simultaneously.
2121

22-
## Make one string from another
23-
24-
Написать метод, на вход которого приходит две строки.
25-
На выходе надо проверить, можно ли получить одну строку из другой за одно исправление:
26-
27-
- замена одного символа в одной строке
28-
- вставка/удаление одного символа из одной строки
29-
30-
Примеры тестовых сценариев:
31-
32-
- first = "a", second = "b" -> true
33-
- first = "ab", second = "b" -> true
34-
- first = "ab", second = "cb" -> true
35-
- first = "ab", second = "ba" -> false
36-
- first = "abcd", second = "abd" -> true
37-
3822
## Сортировки:
3923

4024
- быстрая

‎src/main/java/by/andd3dfx/string/StringTransformation.java‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import org.apache.commons.lang3.StringUtils;
44

5+
import static org.apache.commons.lang3.math.NumberUtils.min;
6+
57
/**
68
* <pre>
79
* Написать метод (класс и импорты не нужны) на вход которого приходит две строки.
@@ -67,4 +69,49 @@ private static boolean remainingPartsShouldBeEqual(String first, int from1, Stri
6769
second.substring(from2)
6870
);
6971
}
72+
73+
public static boolean couldTransformUsingLevenshteinDistance(String first, String second) {
74+
return levenshteinDistance(first, second) <= 1;
75+
}
76+
77+
/**
78+
* Use Wagner-Fisher algorithm. For details check
79+
* <a href="https://habr.com/ru/articles/676858/">article1</a>,
80+
* <a href="https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm">article2</a>
81+
*
82+
* @param str1 First string
83+
* @param str2 Second string
84+
* @return Levenshtein distance
85+
*/
86+
public static int levenshteinDistance(String str1, String str2) {
87+
var m = str1.length();
88+
var n = str2.length();
89+
// for all i and j, d[i,j] will hold the distance between
90+
// the first i characters of s and the first j characters of t
91+
// note that d has (m+1)*(n+1) values
92+
var d = new int[m + 1][n + 1];
93+
94+
// source prefixes can be transformed into empty string by
95+
// dropping all characters
96+
for (int i = 1; i <= m; i++) {
97+
d[i][0] = i;
98+
}
99+
100+
// target prefixes can be reached from empty source prefix
101+
// by inserting every character
102+
for (int j = 1; j <= n; j++) {
103+
d[0][j] = j;
104+
}
105+
106+
for (int j = 1; j <= n; j++) {
107+
for (int i = 1; i <= m; i++) {
108+
var substitutionCost = (str1.charAt(i - 1) == str2.charAt(j - 1)) ? 0 : 1;
109+
110+
d[i][j] = min(d[i - 1][j] + 1, // deletion
111+
d[i][j - 1] + 1, // insertion
112+
d[i - 1][j - 1] + substitutionCost); // substitution
113+
}
114+
}
115+
return d[m][n];
116+
}
70117
}

‎src/test/java/by/andd3dfx/string/StringTransformationTest.java‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.junit.Test;
44

55
import static by.andd3dfx.string.StringTransformation.couldTransform;
6+
import static by.andd3dfx.string.StringTransformation.couldTransformUsingLevenshteinDistance;
67
import static org.assertj.core.api.Assertions.assertThat;
78

89
public class StringTransformationTest {
@@ -12,32 +13,51 @@ public void couldTransform_changeOneChar() {
1213
assertThat(couldTransform("a", "b")).isTrue(); // change one char, 1-char string
1314
assertThat(couldTransform("a1b", "c1b")).isTrue(); // change one (first) char
1415
assertThat(couldTransform("a1b", "a1d")).isTrue(); // change one (last) char
16+
17+
assertThat(couldTransformUsingLevenshteinDistance("a", "b")).isTrue(); // change one char, 1-char string
18+
assertThat(couldTransformUsingLevenshteinDistance("a1b", "c1b")).isTrue(); // change one (first) char
19+
assertThat(couldTransformUsingLevenshteinDistance("a1b", "a1d")).isTrue(); // change one (last) char
1520
}
1621

1722
@Test
1823
public void couldTransform_removeOneChar() {
1924
assertThat(couldTransform("abcd", "bcd")).isTrue(); // remove one (first) char
2025
assertThat(couldTransform("abcd", "acd")).isTrue(); // remove one (inner) char
2126
assertThat(couldTransform("abcd", "abc")).isTrue(); // remove one (last) char
27+
28+
assertThat(couldTransformUsingLevenshteinDistance("abcd", "bcd")).isTrue(); // remove one (first) char
29+
assertThat(couldTransformUsingLevenshteinDistance("abcd", "acd")).isTrue(); // remove one (inner) char
30+
assertThat(couldTransformUsingLevenshteinDistance("abcd", "abc")).isTrue(); // remove one (last) char
2231
}
2332

2433
@Test
2534
public void couldTransform_addOneChar() {
2635
assertThat(couldTransform("bcd", "abcd")).isTrue(); // add one (first) char
2736
assertThat(couldTransform("abd", "abcd")).isTrue(); // add one (inner) char
2837
assertThat(couldTransform("abc", "abcd")).isTrue(); // add one (last) char
38+
39+
assertThat(couldTransformUsingLevenshteinDistance("bcd", "abcd")).isTrue(); // add one (first) char
40+
assertThat(couldTransformUsingLevenshteinDistance("abd", "abcd")).isTrue(); // add one (inner) char
41+
assertThat(couldTransformUsingLevenshteinDistance("abc", "abcd")).isTrue(); // add one (last) char
2942
}
3043

3144
@Test
3245
public void couldTransform_significantlyDifferentLengths() {
3346
assertThat(couldTransform("abcd", "ab")).isFalse();
3447
assertThat(couldTransform("bc", "abcd")).isFalse();
48+
49+
assertThat(couldTransformUsingLevenshteinDistance("abcd", "ab")).isFalse();
50+
assertThat(couldTransformUsingLevenshteinDistance("bc", "abcd")).isFalse();
3551
}
3652

3753
@Test
3854
public void couldTransform_transformIsNotPossible() {
3955
assertThat(couldTransform("ab", "ba")).isFalse(); // same lengths
4056
assertThat(couldTransform("abcde", "abdm")).isFalse(); // different lengths
4157
assertThat(couldTransform("abdm", "abcde")).isFalse(); // different lengths
58+
59+
assertThat(couldTransformUsingLevenshteinDistance("ab", "ba")).isFalse(); // same lengths
60+
assertThat(couldTransformUsingLevenshteinDistance("abcde", "abdm")).isFalse(); // different lengths
61+
assertThat(couldTransformUsingLevenshteinDistance("abdm", "abcde")).isFalse(); // different lengths
4262
}
4363
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /