Skip to content

Commit

Permalink
problem: new problem solution - 1657 . Determine if Two Strings Are C…
Browse files Browse the repository at this point in the history
…lose
  • Loading branch information
squxq committed Jan 14, 2024
1 parent 73baf6f commit f2834f0
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ My approach to solving LeetCode problems typically involves the following steps:
| 334 | [Increasing Triplet Subsequence](https://leetcode.com/problems/increasing-triplet-subsequence/) | Algorithms | [TypeScript](./problems/algorithms/increasingTripletSubsequence/IncreasingTripletSubsequence.ts) | Medium |
| 1347 | [Minimum Number of Steps to Make Two Strings Anagram](https://leetcode.com/problems/minimum-number-of-steps-to-make-two-strings-anagram/) | Algorithms | [TypeScript](./problems/algorithms/minimumNumberOfStepsToMakeTwoStringsAnagram/MinimumNumberOfStepsToMakeTwoStringsAnagram.ts) | Medium |
| 3005 | [Count Elements With Maximum Frequency](https://leetcode.com/problems/count-elements-with-maximum-frequency/) | Algorithms | [TypeScript](./problems/algorithms/countElementsWithMaximumFrequency/CountElementsWithMaximumFrequency.ts) | Easy |
| 1657 | [Determine if Two Strings Are Close](https://leetcode.com/problems/determine-if-two-strings-are-close/) | Algorithms | [TypeScript](./problems/algorithms/determineIfTwoStringsAreClose/DetermineIfTwoStringsAreClose.ts) | Medium |
| ... | ... | ... | ... | ... |

In this table:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Source : https://leetcode.com/problems/determine-if-two-strings-are-close/
// Author : francisco
// Date : 2024-01-14

import { closeStrings } from "./DetermineIfTwoStringsAreClose";

describe("determine if two strings are close", () => {
test("example 1", () => {
const result: boolean = closeStrings("abc", "bca");

expect(result).toBe(true);
});

test("example 2", () => {
const result: boolean = closeStrings("a", "aa");

expect(result).toBe(false);
});

test("example 3", () => {
const result: boolean = closeStrings("cabbba", "abbccc");

expect(result).toBe(true);
});

test("additional testcase 4", () => {
const result: boolean = closeStrings("sadjkfasjfkg", "sadjkfasjfk");

expect(result).toBe(false);
});

test("additional testcase 5", () => {
const result: boolean = closeStrings("abbccc", "addccc");

expect(result).toBe(false);
});

test("failed submission - 117 / 153 testcases passed", () => {
const result: boolean = closeStrings("abbbzcf", "babzzcz");

expect(result).toBe(false);
});

test("failed submission - 132 / 153 testcases passed", () => {
const result: boolean = closeStrings("abbzzca", "babzzcz");

expect(result).toBe(false);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Source : https://leetcode.com/problems/determine-if-two-strings-are-close/
// Author : francisco
// Date : 2024-01-14

/*****************************************************************************************************
*
* Two strings are considered close if you can attain one from the other using the following
* operations:
*
* Operation 1: Swap any two existing characters.
*
* For example, abcde -> aecdb
*
* Operation 2: Transform every occurrence of one existing character into another existing
* character, and do the same with the other character.
*
* For example, aacabb -> bbcbaa (all a's turn into b's, and all b's turn into a's)
*
* You can use the operations on either string as many times as necessary.
*
* Given two strings, word1 and word2, return true if word1 and word2 are close, and false otherwise.
*
* Example 1:
*
* Input: word1 = "abc", word2 = "bca"
* Output: true
* Explanation: You can attain word2 from word1 in 2 operations.
* Apply Operation 1: "abc" -> "acb"
* Apply Operation 1: "acb" -> "bca"
*
* Example 2:
*
* Input: word1 = "a", word2 = "aa"
* Output: false
* Explanation: It is impossible to attain word2 from word1, or vice versa, in any number of
* operations.
*
* Example 3:
*
* Input: word1 = "cabbba", word2 = "abbccc"
* Output: true
* Explanation: You can attain word2 from word1 in 3 operations.
* Apply Operation 1: "cabbba" -> "caabbb"
* Apply Operation 2: "caabbb" -> "baaccc"
* Apply Operation 2: "baaccc" -> "abbccc"
*
* Constraints:
*
* 1 <= word1.length, word2.length <= 10^5
* word1 and word2 contain only lowercase English letters.
******************************************************************************************************/

/**
* @param {string} word1
* @param {string} word2
* @returns {boolean}
* return true if word1 and word2 are close, and false otherwise
* NOTE: close means - same length && same characters && same counts
* Tests:
* I: word1 = "abc", word2 = "bca" -> O: true
* I: word1 = "a", word2 = "aa" -> O: false
* I: word1 = "cabbba", word2 = "abbccc" -> O: true
* I: word1 = "sadjkfasjfkg", word2 = "sadjkfasjfk" -> O: false
* I: word1 = "abbccc", word2 = "addccc" -> O: false
* I: word1 = "abbbzcf", word2 = "babzzcz" -> O: false
* I: word1 = "abbzzca", word2 = "babzzcz" -> O: false
* Template:
* if the lengths are different they cannot be close
* iterate word 1 and get its characters and character counts, counts1
* iterate word 2: check if any of the characters in word 2 is not in counts1
* add word 2's counts to its own variable
* iterate each word's counts: hashtable for the frequency of certain count
* for word 1's counts add 1 to the frequency, for word 2's counts sub 1 from frequency
* if every frequency is zero it means there is the same number of counts for each word
* Time Complexity: O(n + max(m, k)), where n is word1.length;
m is values1.length and k is values2.length
* Space Complexity: O(m + k)
*/
export function closeStrings(word1: string, word2: string): boolean {
// same length
if (word1.length !== word2.length) return false;

const counts1: Record<string, number> = {};
const counts2: Record<string, number> = {};

for (let i: number = 0; i < word1.length; i++) {
counts1[word1[i] as string] = (counts1[word1[i] as string] ?? 0) + 1;
}

for (let i: number = 0; i < word2.length; i++) {
// same characters
if (counts1[word2[i] as string] === undefined) return false;
counts2[word2[i] as string] = (counts2[word2[i] as string] ?? 0) + 1;
}

const values1: number[] = Object.values(counts1);
const values2: number[] = Object.values(counts2);

const counts: Record<number, number> = {};

for (let i: number = 0; i < values1.length; i++) {
counts[values1[i] as number] = (counts[values1[i] as number] ?? 0) + 1;
counts[values2[i] as number] = (counts[values2[i] as number] ?? 0) - 1;
}

// same counts
return Object.values(counts).every((count: number) => count === 0);
}

0 comments on commit f2834f0

Please sign in to comment.