package com.interview.algorithms.list;
import com.interview.datastructures.list.Node;
import java.util.HashMap;
public class FindSubListWithAllColors {
class SubList {
Node start, end;
int length;
public SubList(Node start, Node end, int length){
this.start = start;
this.end = end;
this.length = length;
}
}
class State {
int stepsFromHeadToEnd = 1, stepsFromHeadToStart = 0, maxSubListLength = Integer.MAX_VALUE;
Node start, end, head;
Node maxSubListStart, maxSubListEnd;
HashMap<String, String> colors = new HashMap<String, String>();
State(Node head){
this.head = head;
this.start = this.end = head;
this.updateColorsForEndNode();
this.end = this.start.next();
this.updateColorsForEndNode();
this.maxSubListStart = this.start;
this.maxSubListEnd = this.end;
this.maxSubListLength = this.getCurrentSubListLength();
}
public boolean isCompleted(){
boolean completed = (stepsFromHeadToStart == 0 && end.next() == head) ||
(stepsFromHeadToStart > 0 && start == head);
return completed;
}
public int getCurrentSubListLength(){
return this.stepsFromHeadToEnd - this.stepsFromHeadToStart;
}
public void updateColorsForEndNode(){
String color = this.end.getValue();
if(this.colors.get(color) == null)
this.colors.put(color, "" + this.stepsFromHeadToEnd);
else {
String offsets = this.colors.get(color) + "," + this.stepsFromHeadToEnd;
this.colors.put(color, offsets);
}
}
}
/**
*
* @param head A cyclic list contains M nodes with N types of colors
* @param colorOffsets
* @return
*/
public State find(Node head, int colorCount) {
State state = new State(head);
while(! state.isCompleted()) {
if(state.colors.size() == colorCount){
int length = state.stepsFromHeadToEnd - state.stepsFromHeadToStart;
if(length < state.maxSubListLength){
state.maxSubListStart = state.start;
state.maxSubListEnd = state.end;
state.maxSubListLength = length;
}
state.colors.remove(state.start.getValue());
state.start = state.start.next();
state.stepsFromHeadToStart ++;
this.compactSubList(state);
} else if(state.start.getValue().equals(state.end.getValue())) // there is always 1 node with the color of start node in current sublist
this.compactSubList(state);
else {
state.end = state.end.next();
state.updateColorsForEndNode();
}
}
return state;
}
/*
* Make the start->end sublist the smallest and contains all current colors.
* The algorithm is to move start node to the node with its color only appeared once and its
* stepsFromHeadToStart is the smallest
*/
private void compactSubList(State state){
while(state.colors.get(state.start.getValue()).split(",").length > 1){
String[] startNodeColors = state.colors.get(state.start.getValue()).split(",");
String colorsString = startNodeColors[1];
for(int i = 2; i < startNodeColors.length; i ++){
colorsString += "," + startNodeColors[i];
}
state.colors.put(state.start.getValue(), colorsString);
state.start = state.start.next();
state.stepsFromHeadToStart ++ ;
}
}
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("a".split(",").length);
}
}