3 options for solving a popular problem

Formulation of the problem

Write a function that returns true if string s can be converted to string t by making no more than one of three changes: removing one character from s, adding one character to s, or replacing one character in s.

  class Solution {
    /*
    Вернуть true, если из строки s можно получить строку t,
    совершив не более, чем одно из 3х изменений]:
    - удалить из s один символ
    - добавить в s один символ
    - заменить в s один символ
    s = aaa t = aaa -> true
    s = baaa t = aaa -> true
    s = aaa t = aaab -> true
    s = aba t = aca -> true
    s = badca t = babba -> false
    s = badca t = badcaaa -> false
    */
    boolean check(String s, String t) {
    }
  }

General simplifications

Removing a character from a string s is equivalent to adding a character to a string t. We go from 3 possible changes to 2 possible ones if we swap s and t so that s is always not shorter t:

boolean check(String s, String t) {
  if(s.equals
  if(s.length() < t.length()) {
    String q = s; 
    s = t; 
    t = q;
  }
  if(s.length() - t.length() > 1) return false;
}

1 solution option

Let's solve a simpler problem. Let's assume that the change is always made with the initial characters of the strings. Let's write an auxiliary function:

boolean checkHelper(String s, String t) {
  return s.substring(1).equals
}

Let's count how many characters in the heads of the lines match. And apply the auxiliary function to the tails of the lines:

boolean check(String s, String t) {
  if(s.equals
  if(s.length() < t.length()) {
    String q = s; 
    s = t; 
    t = q;
  }
  if(s.length() - t.length() > 1) return false;
  int i = 0;
  for(; i < t.length(); i++) {
    if(s.charAt(i) != t.charAt(i)) break;
  }
  return checkHelper(s.substring(i), t.substring(i));
}

Let's check the solution:

Hidden text
  public static void main(String[] args) {
    Solution s = new Solution();
    System.out.println("check true");
    System.out.println(s.check("aaa", "aaa"));
    System.out.println(s.check("baaa", "aaa"));
    System.out.println(s.check("aaa", "baaa"));
    System.out.println(s.check("caaa", "baaa"));
    System.out.println(s.check("aaa", "aaab"));
    System.out.println(s.check("aaab", "aaa"));
    System.out.println(s.check("aaab", "aaac"));
    System.out.println(s.check("aaba", "aaa"));
    System.out.println(s.check("aaa", "aaba"));
    System.out.println(s.check("aaba", "aaca"));
    System.out.println("check false");
    System.out.println(s.check("bcaaa", "aaa"));
    System.out.println(s.check("aaa", "bcaaa"));
    System.out.println(s.check("efaaa", "ghaaa"));
    System.out.println(s.check("aaa", "aaabc"));
    System.out.println(s.check("aaabc", "aaa"));
    System.out.println(s.check("aaaef", "aaagh"));
    System.out.println(s.check("aabca", "aaa"));
    System.out.println(s.check("aaa", "aabca"));
    System.out.println(s.check("aaefa", "aagha"));
  }

Conclusion:

check true
true
true
true
true
true
true
true
true
true
true
check false
false
false
false
false
false
false
false
false
false

Option 2 solution

You can do without substring. But the code will be more cumbersome:

boolean check(String s, String t) {
  if(s.equals
  if(s.length() < t.length()) {
    String q = s; 
    s = t; 
    t = q;
  }
  if(s.length() - t.length() > 1) return false;
  int i = 0;
  for(; i < t.length(); i++) {
    if(s.charAt(i) != t.charAt(i)) break;
  }
  return checkHelper(s, t, i);
}

boolean checkHelper(String s, String t, int i) {
  int si = i + 1;
  int ti = (s.length() == t.length()) ? (i + 1) : i;
  for(; ti < t.length(); si++, ti++) {
    if(s.charAt(si) != t.charAt(ti)) 
      return false;
  }
  return true;
}

Option 3 solution

Let's move the code for counting matching characters in the heads of lines to an auxiliary function:

int checkHelper(String s, String t) {
  int i = 0;
  for(; i < t.length(); i++) {
    if(s.charAt(i) != t.charAt(i)) break;
  }
  return i;
}

We will solve the problem by counting the lengths of common subsequences in the heads of the rows and in the tails.

String reverse(String s) {
  return new StringBuilder(s).reverse().toString();
}

boolean check(String s, String t) {
  if(s.equals
  if(s.length() < t.length()) {
    String q = s; 
    s = t; 
    t = q;
  }
  if(s.length() - t.length() > 1) return false;
  int i = checkHelper(s, t);
  int j = checkHelper(reverse(s), reverse
  return i + j >= t.length() - 1;
}

Summary

All solutions work in linear time. I personally find the first solution more readable. But it is easy to make a mistake in the auxiliary function with substring – if the order of conditions in the logical OR is incorrect, there will be an array out of bounds error.

Thank you for reading my article. Subscribe to my channel:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *