Skip to content

Commit 6330d40

Browse files
committed
Added WildcardSearchDS, NimGame
1 parent 202ef21 commit 6330d40

File tree

3 files changed

+200
-0
lines changed

3 files changed

+200
-0
lines changed

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ A collection of solution to the data structure and algorithm problems
135135
| [SingleNumberII](src/questions/SingleNumberII.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given an integer array nums where every element appears three times except for one, which appears exactly once. Find the single element and return it. <br> [Source](https://leetcode.com/problems/single-number-ii/)</sup> |
136136
| [NextGreaterElementII](src/questions/NextGreaterElementII.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given a circular integer array nums (i.e., the next element of nums[nums.length - 1] is nums[0]), return the next greater number for every element in nums. The next greater number of a number x is the first greater number to its traversing-order next in the array, which means you could search circularly to find its next greater number. If it doesn't exist, return -1 for this number. <br> [Source](https://leetcode.com/problems/next-greater-element-ii/)</sup> |
137137
| [ArrayPartitionI](src/questions/ArrayPartitionI.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given an integer array nums of 2n integers, group these integers into n pairs (a1, b1), (a2, b2), ..., (an, bn) such that the sum of min(ai, bi) for all i is maximized. Return the maximized sum. [Source](https://leetcode.com/problems/array-partition-i/)</sup> |
138+
| [WildcardSearchDS](src/questions/WildcardSearchDS.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Design a data structure that supports adding new words and finding if a string matches any previously added string. Your data structure should implement two methods <br>* `addWord(word)`- Adds word to the data structure <br>* `searchWorld(word)`- Returns true if there is any string in the data structure that matches word. Word may contain dots where a dot can be matched with any letter (a dot represents a wildcard).</sup> |
138139
| [MaxAreaOfIsland](src/questions/MaxAreaOfIsland.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>You are given an m x n binary matrix grid. An island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water. Return the maximum area of an island in grid. If there is no island, return 0. <img src="https://assets.leetcode.com/uploads/2021/05/01/maxarea1-grid.jpg" height="150" width="150"/> [Source](https://leetcode.com/problems/max-area-of-island)</sup> |
139140
| [LengthOfLastWord](src/questions/LengthOfLastWord.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given a string s consisting of some words separated by some number of spaces, return the length of the last word in the string. A word is a maximal substring consisting of non-space characters only. <br> [Source](https://leetcode.com/problems/length-of-last-word)</sup> |
140141
| [HammingDistance](src/questions/HammingDistance.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Given two integers x and y, return the Hamming distance between them. [Source](https://leetcode.com/problems/hamming-distance/)</sup> |
@@ -148,6 +149,7 @@ A collection of solution to the data structure and algorithm problems
148149
| [RangeSumQueryMutable](src/questions/RangeSumQueryMutable.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given an integer array nums, handle multiple queries of the following types: <br>* Update the value of an element in nums. <br>* Calculate the sum of the elements of nums between indices left and right inclusive where left <= right. <br> [Source](https://leetcode.com/problems/range-sum-query-mutable/)</sup> |
149150
| [PascalTriangle](src/questions/PascalTriangle.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given an integer numRows, return the first numRows of Pascal's triangle. In Pascal's triangle, each number is the sum of the two numbers directly above it as shown: <br> <img src="https://upload.wikimedia.org/wikipedia/commons/0/0d/PascalTriangleAnimated2.gif" height="150" width="150"/> [Source](https://leetcode.com/problems/pascals-triangle/)</sup> |
150151
| [ExcelSheetColumnTitle](src/questions/ExcelSheetColumnTitle.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given an integer columnNumber, return its corresponding column title as it appears in an Excel sheet. `A -> 1, B -> 2, C -> 3, Z -> 26, AA -> 27, AB -> 28` <br> [Source](https://leetcode.com/problems/excel-sheet-column-title/)</sup> |
152+
| [NimGame](src/questions/NimGame.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>You are playing the following Nim Game with your friend: <br> <br>* Initially, there is a heap of stones on the table. <br>* You and your friend will alternate taking turns, and you go first. <br>* On each turn, the person whose turn it is will remove 1 to 3 stones from the heap. <br>* The one who removes the last stone is the winner. <br> Given n, the number of stones in the heap, return true if you can win the game assuming both you and your friend play optimally, otherwise return false. <br> [Source](https://leetcode.com/problems/nim-game/)[Solution](https://leetcode.com/problems/nim-game/discuss/73749/Theorem:-all-4s-shall-be-false)</sup> |
151153
| [ValidPalindrome](src/questions/ValidPalindrome.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given a string s, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.</sup> |
152154
| [LongestPalindrome](src/questions/LongestPalindrome.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>Given a string s which consists of lowercase or uppercase letters, return the length of the longest palindrome that can be built with those letters. <br> Letters are case sensitive, for example, "Aa" is not considered a palindrome here. <br> [Source](https://leetcode.com/problems/longest-palindrome/)</sup> |
153155
| [PlusOne](src/questions/PlusOne.kt) <br><sub>Kotlin &#8226; questions</sub> | <sup>You are given a large integer represented as an integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from most significant to least significant in left-to-right order. The large integer does not contain any leading 0's. Increment the large integer by one and return the resulting array of digits. <br> [Source](https://leetcode.com/problems/plus-one/)</sup> |

Diff for: src/questions/NimGame.kt

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package questions
2+
3+
import _utils.UseCommentAsDocumentation
4+
import utils.shouldBe
5+
6+
/**
7+
* You are playing the following Nim Game with your friend:
8+
*
9+
* * Initially, there is a heap of stones on the table.
10+
* * You and your friend will alternate taking turns, and you go first.
11+
* * On each turn, the person whose turn it is will remove 1 to 3 stones from the heap.
12+
* * The one who removes the last stone is the winner.
13+
*
14+
* Given n, the number of stones in the heap, return true if you can win the game assuming
15+
* both you and your friend play optimally, otherwise return false.
16+
*
17+
* [Source](https://leetcode.com/problems/nim-game/) – [Solution](https://leetcode.com/problems/nim-game/discuss/73749/Theorem:-all-4s-shall-be-false)
18+
*/
19+
@UseCommentAsDocumentation
20+
private fun canWinNim(n: Int): Boolean {
21+
// Anyone who gets a 4 is destined to lose as other player gets either 1,2,3 stones remaining
22+
return n % 4 != 0
23+
}
24+
25+
// if (n <= 3) {
26+
// return true
27+
// }
28+
// val memo = Array<Boolean?>(n + 1) { null }
29+
// return playNim(n - 1, true, memo)
30+
// || playNim(n - 2, true, memo)
31+
// || playNim(n - 3, true, memo)
32+
//}
33+
//
34+
//private fun playNim(remaining: Int, iRemovedIt: Boolean, memo: Array<Boolean?>): Boolean {
35+
// if (memo.getOrNull(remaining) != null) {
36+
// return memo[remaining]!!
37+
// }
38+
// if (remaining == 0) {
39+
// return iRemovedIt
40+
// }
41+
// if (remaining <= 3 && iRemovedIt) {
42+
// return false
43+
// } else if (remaining <= 3 && !iRemovedIt) {
44+
// return true
45+
// } else if (remaining == 4 && iRemovedIt) {
46+
// return true
47+
// }
48+
// return playNim(remaining - 1, !iRemovedIt, memo).also { println("${remaining - 1} == $it") }
49+
// || playNim(remaining - 2, !iRemovedIt, memo).also { println("${remaining - 2} == $it") }
50+
// || playNim(remaining - 3, !iRemovedIt, memo).also { println("${remaining - 3} == $it") }
51+
//
52+
//}
53+
//
54+
fun main() {
55+
canWinNim(8) shouldBe false
56+
canWinNim(5) shouldBe true
57+
canWinNim(4) shouldBe false
58+
canWinNim(2) shouldBe true
59+
canWinNim(1) shouldBe true
60+
61+
}

Diff for: src/questions/WildcardSearchDS.kt

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import _utils.UseCommentAsDocumentation
2+
import kotlin.test.assertFalse
3+
import kotlin.test.assertTrue
4+
5+
/**
6+
* Design a data structure that supports adding new words and finding if a string matches any previously added string.
7+
* Your data structure should implement two methods
8+
* * `addWord(word)`- Adds word to the data structure
9+
* * `searchWorld(word)`- Returns true if there is any string in the data structure that matches word. Word may contain dots where a dot can be matched with any letter (a dot represents a wildcard).
10+
*/
11+
@UseCommentAsDocumentation
12+
class Trie {
13+
var value: Char? = null
14+
15+
private val trieMap: MutableMap<Char, Trie> = mutableMapOf()
16+
17+
fun addWord(word: String) {
18+
addWord(word, 0)
19+
}
20+
21+
private fun addWord(word: String, index: Int) {
22+
val letter = word.getOrNull(index) ?: return
23+
if (letter !in trieMap) {
24+
val newTrie = Trie()
25+
trieMap[letter] = newTrie
26+
newTrie.value = letter
27+
newTrie.addWord(word, index + 1)
28+
} else {
29+
val trie = trieMap[letter]!!
30+
trie.addWord(word, index + 1)
31+
}
32+
}
33+
34+
override fun toString(): String {
35+
return "Trie($value, ${trieMap.values})"
36+
}
37+
38+
private fun depthFirstTraversal(trie: Trie, current: String, word: MutableList<String>) {
39+
if (trie.trieMap.isEmpty()) {
40+
word.add(current)
41+
}
42+
trie.trieMap.forEach { (k, v) ->
43+
depthFirstTraversal(v, current + k, word)
44+
}
45+
}
46+
47+
fun searchWord(word: String): Boolean {
48+
return searchWord(word, 0)
49+
}
50+
51+
private fun searchWord(word: String, index: Int): Boolean {
52+
val letter = word.getOrNull(index) ?: return true
53+
if (letter == '.') { // wildcard
54+
// Ignore this and try to find any other node that matches next character
55+
return trieMap.values.map {
56+
it.searchWord(word, index + 1)
57+
}.any { it }
58+
} else {
59+
val nextTrie = trieMap[letter] ?: return false
60+
return nextTrie.searchWord(word, index + 1)
61+
}
62+
}
63+
64+
65+
fun branches(): List<String> {
66+
val words = mutableListOf<String>()
67+
depthFirstTraversal(this, "", words)
68+
println(words)
69+
return words
70+
}
71+
}
72+
73+
fun main() {
74+
run {
75+
val trie = Trie()
76+
trie.addWord("hello")
77+
trie.addWord("word")
78+
trie.addWord("woke")
79+
trie.addWord("world")
80+
81+
assertTrue { trie.searchWord("hello") }
82+
assertTrue { trie.searchWord("word") }
83+
assertFalse { trie.searchWord("worry") }
84+
assertTrue { trie.searchWord("wo.d") }
85+
assertTrue { trie.searchWord("wor.d") }
86+
87+
trie.addWord("wore")
88+
trie.addWord("wop")
89+
trie.addWord("won")
90+
trie.addWord("worst")
91+
92+
assertTrue { trie.searchWord("wor.t") }
93+
assertFalse { trie.searchWord("wor.ts") }
94+
assertFalse { trie.searchWord("worm") }
95+
trie.addWord("worm")
96+
assertTrue { trie.searchWord("worm") }
97+
assertTrue { trie.searchWord("w.rm") }
98+
assertTrue { trie.searchWord("w..m") }
99+
assertTrue { trie.searchWord("...m") }
100+
assertFalse { trie.searchWord("...ms") }
101+
assertTrue { trie.searchWord("w...") }
102+
}
103+
104+
run {
105+
val trie = Trie()
106+
trie.addWord("egg")
107+
trie.addWord("eggplant")
108+
trie.addWord("eggshell")
109+
trie.addWord("elephant")
110+
trie.addWord("eleanor")
111+
trie.addWord("eleven")
112+
trie.addWord("elegant")
113+
trie.addWord("evil")
114+
115+
116+
assertTrue { trie.searchWord("egg") }
117+
assertTrue { trie.searchWord("eg.") }
118+
assertTrue { trie.searchWord("eg.p.a.t") }
119+
assertTrue { trie.searchWord("elep.a.t") }
120+
assertFalse { trie.searchWord("elope") }
121+
assertFalse { trie.searchWord("el.phat") }
122+
assertFalse { trie.searchWord("elev.ns") }
123+
assertFalse { trie.searchWord("elevens") }
124+
assertFalse { trie.searchWord("eleventh") }
125+
assertFalse { trie.searchWord("eleven.") }
126+
127+
trie.addWord("watch")
128+
trie.addWord("witch")
129+
trie.addWord("with")
130+
trie.addWord("without")
131+
trie.addWord("withe")
132+
trie.addWord("wither")
133+
trie.addWord("wit")
134+
trie.addWord("withering")
135+
trie.branches()
136+
}
137+
}

0 commit comments

Comments
 (0)