One edit distance

LeetCode problem 161. One Edit Distance.

## Problem description

Given two strings `s` and `t`, return `true` if they are both one edit distance apart, otherwise return `false`.

A string `s` is said to be one distance apart from a string `t` if you can:

* Insert **exactly one** character into `s` to get `t`.
* Delete **exactly one** character from `s` to get `t`.
* Replace **exactly one** character of `s` with **a different character** to get `t`.

Example 1
**Input:** `s = "ab", t = "acb"`
**Output:** true
**Explanation:** We can insert 'c' into s to get t.
Example 2
**Input:** `s = "", t = ""`
**Output:** false
**Explanation:** We cannot get t from s by only one step.
Example 3
**Input:** `s = "a", t = ""`
**Output:** true
Example 4
**Input:** `s = "", t = "A"`
**Output:** true

Constraints
* `0 <= s.length <= 104`
* `0 <= t.length <= 104`
* `s` and `t` consist of lower-case letters, upper-case letters **and/or** digits.

## Analysis

While one may be tempted to solve the Edit distance problem first, it is actually not needed to do so.

We notice several facts that can lessen our burden of computation:

* If the two strings are the same, then return false.
* If the two strings' lengths differ by 2 or greater, then return false.
* Two strings that are one edit distance apart either have the same length (i.e. one character is replaced) or have length difference of 1 (i.e. one character is inserted / deleted).

So we can do the following:

1. Check if the two strings are equal. If equal, then return false.
2. Check if the two strings' lengths differ by 2 or greater. If yes, then return false.
3. Check if `str1.length() < str2.length()`. If yes, we we swap the order of the two strings and recursively call the function.
4. Consider the following cases:
	* **`str1.length() == str2.length()`**
		1. Set `foundDiff = false`.
		2. Traverse both strings from left to right. Compare them character by character.
			+ If `str1[i] != str2[i]`:
				- If `foundDiff == true` then return false.
				- Otherwise set `foundDiff = true`. Progress to the next position.
			+ Otherwise progress to the next position.
		3. If we have traversed to the end, then return true.
	* **`str1.length() == str2.length() + 1`**
		1. Set `foundDiff = false`.
		2. Traverse both strings from left to right. Compare them character by character.
			+ If `foundDiff == true`:
				- If `str1[i+1] != str2[i]`, then return false.
				- Otherwise progress to next position.
			+ Otherwise:
				- If `str1[i] != str2[i]`, then set `foundDiff = true`. Keep the same `i` and move on to compare `str1[i+1]` vs. `str2[i]`.
				- Otherwise move on to the next `i`.
		3. If we have traversed to the end, then return true.

### Complexity analysis

#### Time complexity

1. Comparing whether two strings are the same takes O(n) time, where *n* is the length of the shorter input string.
2. Since we traverse the two strings character by character, the time complexity for this is O(n), where *n* is again the length of the shorter input string.

So the total time complexity is **O(n)**.

#### Space complexity

Stack
Since we only have at most one level of recursion, and other auxiliary variables take constant space, the space complexity on stack is O(1).
Heap
Since we did not allocate any new objects, the space complexity on heap is O(1).
So the total space complexity is **O(1)**.

## Solution

### C++ solution

```
class Solution {
public:
 bool isOneEditDistance(const std::string& s, const std::string& t) {
 // corner case: if two strings are the same
 if (s == t) {
 return false;
 }

 // first check length difference
 if (std::abs(static\_cast<int>(s.length() - t.length())) >= 2) {
 return false;
 }

 // swap order if s.length() < t.length()
 // so that s.length() >= t.length()
 if (s.length() < t.length()) {
 return isOneEditDistance(t, s);
 }

 bool foundDiff = false;

 // if both strings have the same length
 // then compare then character by character
 // only one pair of different characters is allowed
 if (s.length() == t.length()) {
 int i = 0;
 while (i < t.length()) {
 if (s[i] != t[i]) {
 if (foundDiff) {
 return false;
 }
 foundDiff = true;
 }
 ++i;
 }
 return true;
 }
 // otherwise s.length() - t.length() == 1
 // two steps:
 // 1. compare s[i] and t[i] iteratively
 // until finding one different pairs of characters
 // 2. compare s[i+1] and t[i] iteratively
 // until reaching the end
 else {
 int i = 0;
 while (i < t.length()) {
 if (foundDiff) {
 if (s[i+1] != t[i]) {
 return false;
 }
 ++i;
 }
 else {
 if (s[i] != t[i]) {
 foundDiff = true;
 continue;
 }
 ++i;
 }
 }
 return true;
 }
 }
};

```

### Java solution

```
class Solution {
 public boolean isOneEditDistance(String s, String t) {
 // corner case: if two strings are the same
 if (s.equals(t)) {
 return false;
 }

 // first check length difference
 if (Math.abs(s.length() - t.length()) >= 2) {
 return false;
 }

 // swap order if s.length() < t.length()
 // so that s.length() >= t.length()
 if (s.length() < t.length()) {
 return isOneEditDistance(t, s);
 }

 boolean foundDiff = false;

 // if both strings have the same length
 // then compare then character by character
 // only one pair of different characters is allowed
 if (s.length() == t.length()) {
 int i = 0;
 while (i < t.length()) {
 if (s.charAt(i) != t.charAt(i)) {
 if (foundDiff) {
 return false;
 }
 foundDiff = true;
 }
 ++i;
 }
 return true;
 }
 // otherwise s.length() - t.length() == 1
 // two steps:
 // 1. compare s[i] and t[i] iteratively
 // until finding one different pairs of characters
 // 2. compare s[i+1] and t[i] iteratively
 // until reaching the end
 else {
 int i = 0;
 while (i < t.length()) {
 if (foundDiff) {
 if (s.charAt(i+1) != t.charAt(i)) {
 return false;
 }
 ++i;
 }
 else {
 if (s.charAt(i) != t.charAt(i)) {
 foundDiff = true;
 continue;
 }
 ++i;
 }
 }
 return true;
 }
 }
}

```

## External links

* Check if edit distance between two strings is one (Archive)