I wrote this code for https://leetcode.com/problems/is-graph-bipartite/
It works but I think the code is terrible. Issues:
- How do I break when I find isBipartite=false
- How do I only dfs(find if graph is bipartite) for g.keys which have not be visted. (when there are 2 graphs not connected to each other )
import scala.collection.immutable.Queue
case class Step(q: Queue[Int]=Queue(),visited: List[Int]=List(),colors: List[Int]=List(),isBipartite: Boolean = true)
object Solution {
def isBipartite(graph: Array[Array[Int]]): Boolean = {
val g= graph.foldLeft(Map[Int,List[Int]]())((mp,arr)=>{
val i= graph.indexOf(arr)
if(arr.isEmpty){
mp + (i->List())
}else
arr.foldLeft(mp)((m,v)=>{
m + (i->(m.getOrElse(i,Nil) :+ v))
})
})
//println(g)
val colors = List.fill(graph.size)(-1)
//println(colors)
g.keys.foldLeft(Step())((s,k)=>{
if(!s.visited.contains(k) || s.isBipartite==true)
bfs(k,g,s.copy(q=Queue(k),visited=(s.visited:+ k),colors=colors.updated(k,1)))
else
s.copy(isBipartite=false)
}).isBipartite
}
def bfs(start: Int, g: Map[Int,List[Int]], step1: Step): Step = {
val s=Stream.iterate(step1) {
case (step) =>
//dequeue
val (vertex, rest)=step.q.dequeue
val newS=g.getOrElse(vertex,Nil).foldLeft(step)((s,v)=>{
//println("vertex color for vertex "+vertex+" "+s.colors(vertex))
//println("v color "+s.colors(v))
if(s.colors(vertex)==s.colors(v)){
//println("is not bipartite")
step.copy(isBipartite=false)
}else if(s.colors(v) == -1){
//println(s.colors)
s.copy(colors=s.colors.updated(v,(1-s.colors(vertex))))
}else{
s
}
})
//add neighbours to queue
val newQueue=rest.enqueue(g.getOrElse(vertex,Nil).filterNot(newS.visited.contains))
//mark neighbours visited
val newVisited: List[Int] = newS.visited ++ g.getOrElse(vertex,Nil)
newS.copy(q=newQueue,visited=newVisited)
}.takeWhile(t=> t.q.nonEmpty).filterNot(n=>n.isBipartite).headOption
if(!s.isEmpty)
s.get
else
Step()
}
}
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…