Skip to content

Commit

Permalink
Implemented 'Longest Word in Dictionary through Deleting' challenge
Browse files Browse the repository at this point in the history
  • Loading branch information
wibosco committed Sep 5, 2024
1 parent abc869f commit 687b9cd
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 4 deletions.
8 changes: 8 additions & 0 deletions LeetCode/LeetCode.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,8 @@
435D41582C899F4D00B19321 /* HeatersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435D41572C899F4D00B19321 /* HeatersTests.swift */; };
435D415A2C89BADF00B19321 /* LongestUncommonSubsequenceII.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435D41592C89BADF00B19321 /* LongestUncommonSubsequenceII.swift */; };
435D415C2C89BB0C00B19321 /* LongestUncommonSubsequenceIITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435D415B2C89BB0C00B19321 /* LongestUncommonSubsequenceIITests.swift */; };
435D415E2C89F49500B19321 /* LongestWordInDictionaryThroughDeleting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435D415D2C89F49500B19321 /* LongestWordInDictionaryThroughDeleting.swift */; };
435D41602C89F4C500B19321 /* LongestWordInDictionaryThroughDeletingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435D415F2C89F4C500B19321 /* LongestWordInDictionaryThroughDeletingTests.swift */; };
435F019B2A0BE2BC00F6B50F /* MaxAreaOfIsland.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435F019A2A0BE2BC00F6B50F /* MaxAreaOfIsland.swift */; };
435F019D2A0BE2F100F6B50F /* MaxAreaOfIslandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435F019C2A0BE2F100F6B50F /* MaxAreaOfIslandTests.swift */; };
435F019F2A0CF0BB00F6B50F /* SurroundedRegions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435F019E2A0CF0BB00F6B50F /* SurroundedRegions.swift */; };
Expand Down Expand Up @@ -1799,6 +1801,8 @@
435D41572C899F4D00B19321 /* HeatersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatersTests.swift; sourceTree = "<group>"; };
435D41592C89BADF00B19321 /* LongestUncommonSubsequenceII.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongestUncommonSubsequenceII.swift; sourceTree = "<group>"; };
435D415B2C89BB0C00B19321 /* LongestUncommonSubsequenceIITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongestUncommonSubsequenceIITests.swift; sourceTree = "<group>"; };
435D415D2C89F49500B19321 /* LongestWordInDictionaryThroughDeleting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongestWordInDictionaryThroughDeleting.swift; sourceTree = "<group>"; };
435D415F2C89F4C500B19321 /* LongestWordInDictionaryThroughDeletingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongestWordInDictionaryThroughDeletingTests.swift; sourceTree = "<group>"; };
435F019A2A0BE2BC00F6B50F /* MaxAreaOfIsland.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MaxAreaOfIsland.swift; sourceTree = "<group>"; };
435F019C2A0BE2F100F6B50F /* MaxAreaOfIslandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MaxAreaOfIslandTests.swift; sourceTree = "<group>"; };
435F019E2A0CF0BB00F6B50F /* SurroundedRegions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurroundedRegions.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2397,6 +2401,7 @@
3D5C90CF27A7F7620035C399 /* LongestSubstringWithoutRepeatingCharacters.swift */,
435D41592C89BADF00B19321 /* LongestUncommonSubsequenceII.swift */,
4399103E2B078BCF0020E9CC /* LongestUnivaluePath.swift */,
435D415D2C89F49500B19321 /* LongestWordInDictionaryThroughDeleting.swift */,
4399104E2B0811A70020E9CC /* LongestZigZagPathInABinaryTree.swift */,
433D27FE2C864FDB00182C14 /* LongPressedName.swift */,
3D5C90B027A7F7620035C399 /* LowestCommonAncestorBinarySearchTree.swift */,
Expand Down Expand Up @@ -2912,6 +2917,7 @@
3D5C922B27A7F76B0035C399 /* LongestSubstringWithoutRepeatingCharactersTests.swift */,
435D415B2C89BB0C00B19321 /* LongestUncommonSubsequenceIITests.swift */,
439910402B078C040020E9CC /* LongestUnivaluePathTests.swift */,
435D415F2C89F4C500B19321 /* LongestWordInDictionaryThroughDeletingTests.swift */,
439910502B0811D30020E9CC /* LongestZigZagPathInABinaryTreeTests.swift */,
433D28002C86501A00182C14 /* LongPressedNameTests.swift */,
3D5C922C27A7F76B0035C399 /* LowestCommonAncestorBinarySearchTreeTests.swift */,
Expand Down Expand Up @@ -3593,6 +3599,7 @@
3D5C916127A7F7630035C399 /* LowestCommonAncestorBinarySearchTree.swift in Sources */,
43F3DF3929E0B61600EDEB1C /* OddEvenLinkedList.swift in Sources */,
4314616F2B8B3959008683E1 /* FindTargetIndicesAfterSortingArray.swift in Sources */,
435D415E2C89F49500B19321 /* LongestWordInDictionaryThroughDeleting.swift in Sources */,
3D46242927E29BDB00A888C1 /* RemoveDuplicatesFromSortedList.swift in Sources */,
3D5C91EF27A7F7630035C399 /* DivideTwoIntegers.swift in Sources */,
436634982AFE5C320087F13F /* IncreasingOrderSearchTree.swift in Sources */,
Expand Down Expand Up @@ -4269,6 +4276,7 @@
43026BD12AFEDB460066473B /* DeepestLeavesSumTests.swift in Sources */,
3D00561E27DA1F6E0086757A /* PermutationsTests.swift in Sources */,
3D8424E127F2421100B91AAB /* RandomizedSetTests.swift in Sources */,
435D41602C89F4C500B19321 /* LongestWordInDictionaryThroughDeletingTests.swift in Sources */,
3D5C92D927A7F76C0035C399 /* NestedListWeightSumIITests.swift in Sources */,
43643B1B2B0E24ED00B9D711 /* PathSumIVTests.swift in Sources */,
3D193ABD27C78D9600E49F08 /* CombinationSumIIITests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import Foundation
//https://leetcode.com/problems/longest-uncommon-subsequence-ii/
struct LongestUncommonSubsequenceII {

//Time: O(n ^ 2) where n is the number of elements in `strs`
//Time: O(n log n + n ^ 2 * m) where n is the number of elements in `strs`
// where m is the number of characters in a `strs` element
//Space: O(n)
//string
//array
Expand Down Expand Up @@ -44,7 +45,7 @@ struct LongestUncommonSubsequenceII {
break
}

if isSubsequence(a, b) {
if isSubsequence(a, of: b) {
foundSubsequence = true
break
}
Expand All @@ -58,15 +59,15 @@ struct LongestUncommonSubsequenceII {
return -1
}

private func isSubsequence(_ a: String, _ b: String) -> Bool {
private func isSubsequence(_ a: String, of b: String) -> Bool {
let a = Array(a)
let b = Array(b)

var p1 = 0
var p2 = 0

while p1 < a.count {
while p2 < b.count, a[p1] != b[p2] {
while p2 < b.count, a[p1] != b[p2] { //fast forward
p2 += 1
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// LongestWordInDictionaryThroughDeleting.swift
// LeetCode
//
// Created by William Boles on 05/09/2024.
//

import Foundation

//https://leetcode.com/problems/longest-word-in-dictionary-through-deleting/
struct LongestWordInDictionaryThroughDeleting {

//Time: O(n * m)) where n is the number of words in `dictionary`
// where m is the number of characters in a word
//Space: O(m + s) where m is the number of characters in a word
// where s is the number of characters in `s`
//array
//string
//two pointers
//fast forward
//subsequence
//
//Solution Description:
//Iterating through the elements in `dictionary` we attempt to see if that element could be a subsequence of `s`. A
//subsequence is a non-contiguous slice of an array i.e. while order is preserved some characters can be skipped over. We
//use two pointers to iterate through `word` and `s` to determine if `word` is a subsequence of `s`. If `word` is a
//subsequence of `s` we compare `word` against `longestWord` using a two tier approach: first we check length then if
//`longestWord` and `word` have the same length we check lexicographical ordering. If `word` is either longer or of equal
//length with a smaller lexicographical order then we set it as `longestWord`. We repeat this process for all elements in
//`dictionary`. Once all elements have been checked we return `longestWord`.
func findLongestWord(_ s: String, _ dictionary: [String]) -> String {
var longestWord = ""

for word in dictionary {
guard word.count <= s.count else { //`word` can't be longer than `s`
continue
}

if isSubsequence(word, of: s) {
if (word.count > longestWord.count) || // longer word?
((word.count == longestWord.count) && (word < longestWord)) { //same length but lexicographical smaller?
longestWord = word
}
}
}

return longestWord
}

private func isSubsequence(_ a: String, of b: String) -> Bool {
let a = Array(a)
let b = Array(b)

var p1 = 0
var p2 = 0

while p1 < a.count {
while p2 < b.count, a[p1] != b[p2] { //fast forward
p2 += 1
}

p1 += 1
p2 += 1
}

return p2 <= b.count
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// LongestWordInDictionaryThroughDeletingTests.swift
// LeetCodeTests
//
// Created by William Boles on 05/09/2024.
//

import XCTest

@testable import LeetCode

final class LongestWordInDictionaryThroughDeletingTests: XCTestCase {

// MARK: - Tests

func test_A() {
let s = "abpcplea"
let dictionary = ["ale","apple","monkey","plea"]

let result = LongestWordInDictionaryThroughDeleting().findLongestWord(s, dictionary)

XCTAssertEqual(result, "apple")
}

func test_B() {
let s = "abpcplea"
let dictionary = ["a","b","c"]

let result = LongestWordInDictionaryThroughDeleting().findLongestWord(s, dictionary)

XCTAssertEqual(result, "a")
}

func test_C() {
let s = "abpcplea"
let dictionary = ["b","c","a"]

let result = LongestWordInDictionaryThroughDeleting().findLongestWord(s, dictionary)

XCTAssertEqual(result, "a")
}

func test_D() {
let s = "abpcplea"
let dictionary = ["ale","apple","monkey","plea", "abpcplaaa","abpcllllll","abccclllpppeeaaaa"]

let result = LongestWordInDictionaryThroughDeleting().findLongestWord(s, dictionary)

XCTAssertEqual(result, "apple")
}
}

0 comments on commit 687b9cd

Please sign in to comment.