Skip to content

Commit 6e45bad

Browse files
committed
feat(scala): initial dump
This commit includes solutions for various leetcode problems written in Scala. The problems cover a wide range of topics from data structures, dynamic programming, tree search, and more.
0 parents  commit 6e45bad

File tree

263 files changed

+12302
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

263 files changed

+12302
-0
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea

Diff for: README.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# LeetCode Solutions Archive
2+
3+
Leetcode profile https://leetcode.com/u/maxmtmn/
4+
5+
These solutions have been collected over years and might have slightly different style, which evolved over time.
6+
Currently, contains `Scala` solutions only.
7+
8+
Welcome to our open-source project - a curated collection of solutions for problems posed on `LeetCode`, all written in
9+
the functional and object-oriented programming language, `Scala`.
10+
11+
This project is a treasure trove for all those interested in improving their algorithmic problem-solving skills,
12+
developers preparing for their next coding interview, or anyone who is a lover of logic and puzzles.
13+
14+
This repository contains numerous individual Scala files, each tailored to solve a unique LeetCode problem. The Scala
15+
files are conveniently named following the Leet's numbering system (`Leet<problem_number>.scala`), which makes it quite
16+
straightforward to find solutions to your problem of interest.
17+
18+
Remember, the purpose of this project is not to endorse the mere copying of solutions but to learn, understand and
19+
internalize the logic and elegance of problem-solving in `Scala`. So, seize this opportunity to deepen your knowledge
20+
and become a better developer.
21+
22+
I welcome your contributions and encourage you to submit pull requests to enhance the quality and diversity of
23+
solutions. Happy learning and coding!

Diff for: scala/Leet1011.scala

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
3+
object Leet1011 extends App {
4+
5+
object Solution {
6+
def shipWithinDays(weights: Array[Int], days: Int): Int = {
7+
// ans is between maxWeight and totalWeight
8+
val totalWeights = weights.sum
9+
var left = weights.max
10+
var right = totalWeights
11+
var result = totalWeights
12+
while (left <= right) {
13+
val mid = (left + right) / 2
14+
val daysWithThisCapacity = minDaysWithCapacity(weights, mid)
15+
if (daysWithThisCapacity <= days) {
16+
result = result min mid
17+
}
18+
if (daysWithThisCapacity <= days) {
19+
// we have extra capacity and can work faster
20+
right = mid - 1
21+
} else {
22+
// not enough capacity
23+
left = mid + 1
24+
}
25+
}
26+
result
27+
}
28+
29+
private def minDaysWithCapacity(weights: Array[Int], capacity: Int): Int = {
30+
weights.foldLeft((1, 0)) {
31+
// fill at the same day
32+
case ((days, used), weight) if used + weight <= capacity =>
33+
(days, used + weight)
34+
// fill at the next day
35+
case ((days, used), weight) =>
36+
(days + 1, weight)
37+
}._1
38+
}
39+
}
40+
41+
}

Diff for: scala/Leet102.scala

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
object Leet102 extends App {
2+
3+
import scala.collection.mutable
4+
5+
class TreeNode(_value: Int = 0, _left: TreeNode = null, _right: TreeNode = null) {
6+
var value: Int = _value
7+
var left: TreeNode = _left
8+
var right: TreeNode = _right
9+
}
10+
11+
object Solution {
12+
def levelOrder(root: TreeNode): List[List[Int]] = {
13+
Option(root).map {
14+
n =>
15+
val levels = mutable.Map.empty[Int, List[Int]].withDefaultValue(List())
16+
traverse(n, levels)
17+
(0 until levels.size).map(l => levels(l)).toList
18+
}.getOrElse(List())
19+
}
20+
21+
private def traverse(node: TreeNode, levels: mutable.Map[Int, List[Int]], level: Int = 0): Unit = {
22+
levels(level) = node.value :: levels(level)
23+
(Option(node.left), Option(node.right)) match {
24+
case (None, Some(r)) => traverse(r, levels, level + 1)
25+
case (Some(l), None) => traverse(l, levels, level + 1)
26+
case (Some(l), Some(r)) =>
27+
traverse(r, levels, level + 1)
28+
traverse(l, levels, level + 1)
29+
case _ =>
30+
}
31+
}
32+
}
33+
}

Diff for: scala/Leet1055.scala

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import scala.collection.mutable
2+
3+
object Leet1055 extends App {
4+
5+
object Solution {
6+
def shortestWay(source: String, target: String): Int = {
7+
if (!target.toSet.subsetOf(source.toSet)) return -1
8+
Iterator.unfold((source.toList, target.toList)) {
9+
// target constructed
10+
case (_, Nil) => None
11+
// source sequence is used, try another sequence
12+
case (Nil, target) => Some(1, (source.toList, target))
13+
// if matches eliminate as much as possible
14+
case (sourceHead :: sourceTail, targetHead :: targetTail) if sourceHead == targetHead => Some(0, (sourceTail, targetTail))
15+
// if doesn't match try next combination
16+
case (_ :: sourceTail, target) => Some(0, (sourceTail, target))
17+
}.sum + 1 //add one because final combination always give 1
18+
}
19+
}
20+
}

Diff for: scala/Leet1058.scala

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import scala.collection.mutable
2+
3+
object Leet1058 extends App {
4+
5+
class Number(numStr: String) {
6+
lazy val floor = numInt - numInt % 1000
7+
lazy val ceil = if (numInt != floor) {
8+
floor + 1000
9+
} else {
10+
floor
11+
}
12+
private val numInt = numStr.split('.') match {
13+
case Array(a, b) => a.toInt * 1000 + b.toInt
14+
case _ => throw new Exception("Invalid input")
15+
}
16+
17+
def toInt() = {
18+
numInt
19+
}
20+
}
21+
22+
class Dfs(prices: Array[Number], target: Int) {
23+
private val target1000 = target * 1000
24+
private val cache = mutable.Set.empty[(Int, Int, Int)]
25+
private var result: Option[Int] = None
26+
27+
def getResult(): Option[Int] = {
28+
result
29+
}
30+
31+
def search(priceId: Int, sum: Int, diff: Int): Unit = {
32+
if (result.exists(_ < diff) || sum > target1000 || cache.contains((priceId, sum, diff))) {
33+
return
34+
} else {
35+
cache += ((priceId, sum, diff))
36+
if (priceId == prices.length) {
37+
if (sum == target1000) {
38+
result = Some(diff)
39+
}
40+
} else {
41+
search(priceId + 1, sum + prices(priceId).floor, diff + (prices(priceId).toInt - prices(priceId).floor).abs)
42+
if (prices(priceId).floor != prices(priceId).ceil) {
43+
search(priceId + 1, sum + prices(priceId).ceil, diff + (prices(priceId).toInt - prices(priceId).ceil).abs)
44+
}
45+
}
46+
}
47+
48+
}
49+
50+
search(0, 0, 0)
51+
}
52+
53+
object Solution {
54+
def minimizeError(prices: Array[String], target: Int): String = {
55+
new Dfs(prices.map(new Number(_)), target)
56+
.getResult
57+
.map(r => "%.3f".format(r.toDouble / 1000))
58+
.getOrElse("-1")
59+
}
60+
61+
}
62+
}

Diff for: scala/Leet1058a.scala

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import scala.collection.mutable
2+
3+
object Leet1058a extends App {
4+
5+
import scala.collection.mutable
6+
7+
class Number(numStr: String) {
8+
val floor = numInt - numInt % 1000
9+
val ceil = if (numInt != floor) {
10+
floor + 1000
11+
} else {
12+
floor
13+
}
14+
private val numInt = numStr.split('.') match {
15+
case Array(a, b) => a.toInt * 1000 + b.toInt
16+
case _ => throw new Exception("Invalid input")
17+
}
18+
19+
def toInt = numInt
20+
}
21+
22+
object Solution {
23+
def minimizeError(prices: Array[String], target: Int): String = {
24+
val nums = prices.map(new Number(_))
25+
val minDiff = nums.map(_.floor).sum
26+
val maxDiff = nums.map(_.ceil).sum
27+
if (minDiff > target * 1000 || maxDiff < target * 1000) {
28+
return "-1"
29+
}
30+
// do not include numbers where ceil operation doesn't give increment of a number
31+
val ceilCosts = mutable.PriorityQueue.from(nums.collect {
32+
case n if n.ceil != n.toInt => n.ceil - n.toInt
33+
})(Asc)
34+
var numberOfCeilRequired = (target * 1000 - minDiff) / 1000
35+
var costPaidToFloor = nums.map(n => n.toInt - n.floor).sum
36+
while (numberOfCeilRequired > 0) {
37+
val costToCeil = ceilCosts.dequeue()
38+
// since costPaidToFloor already includes floor cost for every option,
39+
// and we want to do ceil instead of floor,
40+
// we need to deduct the paid cost first
41+
costPaidToFloor -= (1000 - costToCeil)
42+
// add cost to ceil
43+
costPaidToFloor += costToCeil
44+
numberOfCeilRequired -= 1
45+
}
46+
"%.3f".format(costPaidToFloor.toDouble / 1000)
47+
}
48+
49+
object Asc extends Ordering[Int] {
50+
def compare(a: Int, b: Int) = {
51+
b compare a
52+
}
53+
}
54+
55+
}
56+
}

Diff for: scala/Leet1062.scala

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
object Leet1062 extends App {
2+
object Solution {
3+
def longestRepeatingSubstring(s: String): Int = {
4+
(s.length - 1 to 1 by -1).foreach {
5+
substrLen =>
6+
s.sliding(substrLen, 1).foldLeft(Set.empty[String]) {
7+
case (aggr, sliding) if aggr.contains(sliding) => return substrLen
8+
case (aggr, sliding) => aggr + sliding
9+
}
10+
}
11+
0
12+
}
13+
}
14+
}

Diff for: scala/Leet113.scala

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import scala.collection.immutable.{AbstractSeq, LinearSeq}
2+
3+
object Leet113 extends App {
4+
val tree = new TreeNode(_value = 5,
5+
_left = new TreeNode(_value = 1,
6+
_left = new TreeNode(_value = 3,
7+
_left = null,
8+
_right = null),
9+
_right = null),
10+
_right = new TreeNode(_value = 2,
11+
_left = new TreeNode(_value = 6,
12+
_left = null,
13+
_right = null),
14+
_right = new TreeNode(_value = 4,
15+
_left = null,
16+
_right = null)))
17+
18+
class TreeNode(_value: Int = 0, _left: TreeNode = null, _right: TreeNode = null) {
19+
var value: Int = _value
20+
var left: TreeNode = _left
21+
var right: TreeNode = _right
22+
}
23+
24+
object Solution {
25+
def pathSum(root: TreeNode, targetSum: Int): List[List[Int]] = {
26+
root match {
27+
// the bottom
28+
case TreeNode(None, None) if targetSum == root.value =>
29+
List(List(root.value))
30+
// the middle
31+
case TreeNode(lOpt, rOpt) =>
32+
// filter possible paths
33+
List(lOpt, rOpt).collect { case Some(node) => node }.map(
34+
node => pathSum(node, targetSum - root.value)
35+
.map(root.value :: _)
36+
) match {
37+
case Nil => List.empty[List[Int]]
38+
case list => list.reduceLeft(_ ++ _)
39+
}
40+
// dead end
41+
case _ => List.empty[List[Int]]
42+
}
43+
}
44+
}
45+
46+
object TreeNode {
47+
def unapply(node: TreeNode): Option[(Option[TreeNode], Option[TreeNode])] = {
48+
Option(node).map(node => (Option(node.left), Option(node.right)))
49+
}
50+
}
51+
52+
println(Solution.pathSum(tree, 6))
53+
}

Diff for: scala/Leet1136.scala

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import scala.collection.mutable
2+
3+
object Leet1136 extends App {
4+
5+
import scala.collection.mutable
6+
7+
object Solution {
8+
def minimumSemesters(n: Int, relations: Array[Array[Int]]): Int = {
9+
// build indegree map and graph
10+
val indegree = mutable.Map.empty[Int, Int]
11+
(1 to n).foreach {
12+
v => indegree(v) = 0
13+
}
14+
val graph = mutable.Map.empty[Int, List[Int]].withDefaultValue(List())
15+
relations.foreach {
16+
case Array(from, to) =>
17+
indegree(to) += 1
18+
graph(from) = to :: graph(from)
19+
}
20+
// find starting points
21+
val queue = mutable.Queue.empty[(Int, Int)]
22+
indegree.foreach {
23+
case (n, in) if in == 0 => queue.enqueue((n, 1))
24+
case _ =>
25+
}
26+
// explore using topological search
27+
var semesters = 0
28+
val needToVisit = mutable.Set.from(1 to n)
29+
while (queue.nonEmpty) {
30+
queue.dequeue() match {
31+
case (n, semester) =>
32+
needToVisit -= n
33+
if (needToVisit.isEmpty) {
34+
return semester
35+
}
36+
graph(n).foreach {
37+
dest =>
38+
indegree(dest) -= 1
39+
if (indegree(dest) == 0) {
40+
queue.enqueue((dest, semester + 1))
41+
}
42+
}
43+
}
44+
}
45+
-1
46+
}
47+
}
48+
49+
}

0 commit comments

Comments
 (0)