Friday, September 11, 2015

[Anagram][Hash Table] Group Anagram

1. Example
anagram means after sorted they have the same string
Collections.sort(item);
Group anagrams together

s= ["eat", "tea", "tan", "ate", "nat", "bat"]
Return
[
["ate", "eat", "tea"]
["nat", "tan"],
["bat"]
]


2. Implementation
Q1: Return List<List<String>>?
A1: since the size of string array is dynamic

Input:["tea","and","ate","eat","den"]
Output:[["tea","ate","eat"],["and"],["den"]]
Expected:[["den"],["and"],["ate","eat","tea"]]

NOTE: each inner list's elements must follow the lexicographic order 
==> Collections.sort(item);
NOTE:
for (List<String> value: map.values()) {

// //Time :O(m*n) or O(m+n) , m is length of string and n is number of string in string array
//Time:O(n* mlogm), n is size of string array, m is the length of each string, assume they are the same
public List> groupAnagrams(String[] strs)
{




      List> res = new List>();
      if (strs == null || strs.length == 0)
          return res;




      
      //HashTable> table = new HashTable> ();
      HashMap<String, List<String>> map = new HashMap<String, List<String>>();




      for (int i = 0; i < strs.length; i++)
      {

           


           char[] charArr = strs[i].toCharArray();
           Arrays.sort(charArr);
           String str = new String(charArr);

           



           //if ( table.containsKey() )
           if (map.containsKey(str))
           {
               //table.get(key).add( strs[i]);
               map.get(str).add( strs[i] );
           }
           else 
           {
               //for (int j = 0 ; j< strs[i];j++)
               ///{
                //(int) (strs[i].charAt(j)-'a')
              // }
              List<String> item = new ArrayList<String>();
              item.add(strs[i]);
              //table.put(, item);
              map.put(str, item)
           }




        
      }






      //NOTE:return all the map values,(map.keySet())
      for (List value: map.values())
      {
           List<String> item = new ArrayList<String>(value);





           Collections.sort(item);





           if (item.size() >0)
              res.add(item);
          
      }



      return res;

    

}
3. Similar Ones
(E) Valid Anagram
(E) Group Shifted Strings

Thursday, September 10, 2015

[Math]Integer to Roman

1. Exmaple
// NOTE: avoid call stack don't put call within loop
s= 1700 = >"MDCC"

s= 24 => "XXIV"

s= 19 => "XIX"

s= 900=>"CM"


2. Implementation
Q1: care for for number 4 and 9
// NOTE: avoid call stack don't put call within loop
List digits = new ArrayList();

digits.add(num/divisor);


StringBuilder res = new StringBuilder(); 

res.append( convert(digits.get(0), 'M', '','') ); 
res.append( convert(digits.get(1), 'C', 'D', 'M') ); 
 res.append( convert(digits.get(2), 'X', 'L', 'C') ); 
 res.append( convert(digits.get(3), 'I', 'V', 'X') );

// NOTE: start from 5 can merge case 5 into here
 for (int i = 5; i< digit;i++)
default: //return ""; 
 // NOTE: return string all in bottom, so just BREAK 
default:
 break;



public String intToRoman(int num)
{



     //validate the input
     if ( num < 0 )
          return "";




         
     int divisor = 1000;
     



     // NOTE: use a data structure to store the digits you want to print out
     List digits = new ArrayList();




     while ( divisor > 0)
     {
         //int digit = num /divisor;
         digits.add(num/divisor);

         // NOTE: avoid call stack don't put call within loop
         //if ( divisor == 1000 )
         //{
         //     res.append();
         //}
         //else if ( divisor == 100)
         //{
         //     res.append();
         //}
         //else if ( divisor =10 )
         //{
         //     res.append();
         //}
         //else if ( divisor ==1)
         //{
         //     res.append();
         //} 


         //num/=divisor;
         num%= divisor;
         divisor/=10;

     }



    

     StringBuilder res = new StringBuilder();
     res.append( convert(digits.get(0), 'M', '','') );
     res.append( convert(digits.get(1), 'C', 'D', 'M') );
     res.append( convert(digits.get(2), 'X', 'L', 'C') );
     res.append( convert(digits.get(3), 'I', 'V', 'X') );


     
     return res.toString();



}
public String convert (int digit, char one, char five, char ten)
{
       
      StringBuilder sb = new StringBuilder();
 
     
      switch(digit)
      {
           case 1:
           case 2:
           case 3:
               for ( int i =0; i < digit ; i++)
               {
                   sb.append(one);
               }        
               break;
           case 4:
               sb.append(one);
               sb.append(five);
               break;
           case 5:
               //sb.append(five);
               //break;
           case 6: 
           case 7:
           case 8:
               sb.append(five);
               //for (int i=0;i< digit -5;i++)
               // NOTE: start from 5 can merge case 5 into here
               for (int i = 5; i< digit;i++)
               {
                   sb.append(one);
               }
               break;
           case 9:
               sb.append(one);
               sb.append(ten);           
               break;
           default:
               //return "";
               // NOTE: return string all in bottom, so just BREAK
               break;
      }


      return sb.toString();


}

3. Similar Ones
(E) Roman to Integer
(M) Integer to English Words

[Two Pointers] Implement strStr()

1. Example

for (int i = 0 ; i <= haystack.length() - needle.length() ; i++)
     for (int j = 0; j < needle.length(); j++)
           haystack[i+j] == needle[j]
NOT EVERYTIME i++
while ( i <=  haystack.length() - needle.length() )
     for (int j = 0 ; j < needle.length();j++)
           haystack[i+j] == needle[j]
         if  haystack and needle first char not match 

             i++;
             break;
         else 
             i +=  j - next[j-1];
             break;


"issip"
00120

012345678910
"mississippi"
"issip"
  "issip" i += j - next[j-1] = 4 -2= 2
issip
issipi
KMP
1. Prefix table
A C A C  A G T
0  0  1  2  3  0  0
first char no shift (0)
for each char, find the same letter before it and if found, last char's shift +1 
                       cannot find the same letter before it, no shift (0)
i + j - ( prefixtable[j]-1 )


for (int i = 1; i < needle.length(); i++) {
int index = next[i - 1];
while (index > 0 && needle.charAt(index) != needle.charAt(i)) {
index = next[index - 1];
}

if (needle.charAt(index) == needle.charAt(i)) {
next[i] = next[i - 1] + 1;
} else {
next[i] = 0;

}


N A N O
0  0  1  0
2. How to do the skip (shift previous same letter(from prefix table) to mismatch index)
A C A C  A G T
0  0  1  2  3  0  0


i=0 1  2    3
A  C  A    T.....................
A1C1A2  C2
                X
          i=2
          A1 C1
          i = i+j - next[j-1] = 0+3 - 1 =2


String compare amongst more than two use INDEX to record matched length
Succeed go to the end and not succeed break, use BOOLEAN FLAG
return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack

n="sub"  h ="submarine"=> return 0
n="ood" h = "food" => return 1

2. Implementation
Q1: compare char to char from one to the other?
A1: Time:O(n*m), how many iterations,  index 0 to index 0 and needle.length() to 0+needle.length
https://www.youtube.com/watch?v=2ogqPWJSftE


public int strStr(String haystack, String needle)
{




    // validate the input
    if (haystack == null || needle == null || neelde.length() ==0)
        return 0;
    if ( needle.length() > haystack.length() )
        return -1;
     




    int[] next = getNext(needle);
    int i = 0;




    // NOTE: since i will jump, we use while loop
    while (  i <= haystack.length() - needle.length()  )
    {
        



        boolean successFlag = true;

        


        for ( int j = 0 ; j < needle.length() ; j++) {
              
              // First letter mismatch, regular shift
              if (  needle.charAt(0)  != haystack.charAt(i)  )
              {
                  successFlag = false;
                  i++;
                  break;
              }
              // Other letter mismatch, jump shift
              else if (   needle.charAt(j) != haystack.charAt(i+j)   )
              {
                   successFlag = false;
                   // NOTE: 
                   i = i + j - next[j-1];
                   break;
              }

        }





        if ( successFlag )
            return i;




    }
    


    
    return -1;



    
}
// Calculate the prefix table,called next table here 
public int[] getNext(String needle)
{




      int[] next = new int[needle.length()];
      next[0] = 0;




      for (int i =1 ; i < needle.length(); i++)
      {
             


             
             int index = next[i-1];




             // Case1: index > 0, search back to find same letter 
             while ( index > 0 && needle.charAt(index) != needle.charAt(i) )
                   index = next[index-1];
             




             //Case2: index=0 or others, compare with the index letter and based on it plus 1
             if (needle.charAt(index) == needle.charAt(i))
                   next[i] = next[i-1] + 1;
             else 
                   next[i] = 0;





      }
        

 

      return next;
 


     
}
// Time:O(m*n), Space:O(1)
public int strStr( String haystack, String needle)
{

      // Validate the input
       if (haystack == null || needle == null || needle.length() == 0)
           return 0;
       if (needle.length() > haystack.length())
           return -1;


       
      //int index = 0;
      //NOTE: haystack.length()-1==== needle.length()-1
      //  hay-1-needle+1=hay-needle(include)    0(include)
      for (int i = 0 ; i <= haystack.length() - needle.length() ; i++)
      {



         // NOTE: to record in case, once false, we are done
         boolean successFlag = true;




         for (int j =0; i < needle.length(); j++)
         {
               if (needle.charAt(j)!=haystack.charAt(i+j)) 
               {
                  break;
                  successFlag = false;
               }
               //index++;                   
         }




         //if (index == needle.length())
         //      return i;
         if (successFlag)
            return i;




      }


      return -1;


}
// Time:O(m+n), Space:O(1)
public int strStr(String haystack, String needle)
{





     // validate the input
     if ( haystack==null || needle == null || neelde.length()==0)
        return 0;
     if ( needle.length() > haystack.length() )
        return -1;






     // NOTE: when doing shift in the haystack, every s            hift remvoe previous first char and add a new last char
     // NOTE: abc = 0*29^2 + 1*29^1 + 2*1
     int base = 29;
     int temp = 1;
     int hashcode = 0;
     for ( int i = needle.length()-1; i >= 0 ; i++)
     {
          hashcode+ = (int)(needle.charAt(i)-'a')*temp;
          temp*=base;
     }





     int temp2 =1;
     int hashcode2 = 0; 
     for(int j = needle.length()-1;j>=0;j++)
     {
         hashcode2+= (int)(haystack.charAt(i)-'a')*temp2;
         temp2*=base;
     }





     if (hashcode == hashcode2)
        return 0;






     temp2/=base;
     //for (int i = 1; i <= haystack.length() - needle.length();i++)
     //{
     //    hashcode2 = (hashcode2 - haystack.charAt(i-1)*temp2)*base + haystack.charAt(i+needle.length()-1);
     //    if (hashcode == hashcode2)
     //         return i;
     //}
     // NOTE: start form the last new element
     for (int i=needle.length(); i < haystack.length();i++)
     {
           hashcode2 = ( hashcode2 - haystack.charAt(i-needle.length()*temp2) )*base + haystack.charAt(i);
           return i-needle.length()+1;
     }




     return -1;




     
}
3. Similar ones
(H) Shortest Palindrome

Wednesday, September 9, 2015

[Math] Roman to Integer

1. Example
Input is guaranteed to be within the range from 1 to 3999

s = "MDCC"=> 1700

s= "XXIV"=>24

s= ""XIX" => 19

s= "CM"=>900

I      V       X
1      5      10
X      L      C
10     50    100
C      D     M
100 500    1000

2. Implementation
Q1: check character and decide what value, what if something like IX
A1: whenever you are at unit 1,10,100 check to see if next are 5,10(for 1),50,100(for 10),,500,1000(for 100)


public int romanToInt(String s)
{

       

       // validate the input
       if (s== null || s.length() == 0)
            return 0;



       s = s.trim();
       if (s.length()==0)
            return 0;

     

       int res = 0;
       for (int i = 0 ; i < s.length(); i ++) 
       {
            char c= s.charAt(i);
            switch(c)
            {






                 case 'I':
                     if ( i+1 < s.length() &&( s.charAt(i+1) == 'V' || s.charAt(i+1)=='X') )
                     {
                        res-=1;
                     }
                     else
                        res+=1; 
                     
                     break;
                 case 'X':
                     if ( i+1 < s.length() &&( s.charAt(i+1)=='L' || s.charAt(i+1)=='C'  ) )
                        res-=10;
                     else 
                        res+= 10;
                     break;
                 case 'C':
                    if ( i < s.length() -1 && (s.charAt(i+1)=='D' || s.charAt(i+1)=='M') )
                    {
                        res -= 100;
                    }
                    else 
                    {
                        res += 100;
                    }
                    break;





                case 'L':
                    res += 50;
                    break;
                case 'D':
                    res += 500;
                    break;
                case 'M':
                    res += 1000;
                    break;
                default:
                    return 0;

            }

       }
}
3. Similar Ones (E)  String to Integer (M) Integer to Roman (M) Integer to Number

[Math] String to Integer (atoi)

1. Example
Possibility to break => Use while loop and an IDNEX
Integer.MAX_VALUE =  2147483647
Integer.MIN_VALUE = -2147483648
Long.MAX_VALUE =  9223372036854775807
Long.MIN_VALUE = -9223372036854775808
"+" and "-"
"456"=>456


2. Implementation
Q1: LSB->MSB
A1: start from LSB to MSB and use res = res*10+ current digit
Q1: special character?
A1: trim and check valid >="0" && <="9"


public int myAtoi(String str)
{

    

     // validate the input
     if ( str == null || str.length() == 0 )   
     {
           return 0;
     }




     str = str.trim();





     // NOTE: could be all spaces
     if ( str.length() == 0)
           return 0;





     boolean negFlag = flase;
     //if ( str.charAt(0) == '-')
     //    negFlag =true; 
     // NOTE: could have no sign, so put an index
     int index = 0; 
     if ( str.charAt(0) == '-' || str.charAt(0) == '+' )
     {
          index++;
          if ( str.charAt(0) == '-')
              negFlag = true;
     }





     //// NOTE: 2147483647
     //int number = 0;
     ////for (int i = str.length()-1 ; i >= 1 ; i ++)
     ////for ( int i = 1 ; i < str.length;i++ )
     //// NOTE: couldbe no sign
     //for (int i = index; i < str.length() ; i++ )
     //{
     //    char c = str.charAt(i);
     //    if ( c >= '0' && c <='9' )
     //    {
     //          
     //          if (  i == str.length() -1 && number >= Integer.MAX_VALUE /10  )
     //             number = (negFlag==true)?Integer.MIN_VALUE:Integer.MAX_VALUE; 
     //          else if ( number == Integer.MAX_VALUE/10 )
     //          {
     //              if ( c >= '7' && c <='9' && negFlag == false)
     //                  return Integer.MAX_VALUE;
     //              else if ( c >='8' && c <='9' && negFlag ==true)
     //                  return Integer.MIN_VALUE;
     //          }
     //          else
     //             //number = number*10 + (int)c;
     //             // NOTE: chat to int - '0'
     //             number = number*10 + (int)(c - '0');
     //    }
     //    else 
     //    {
     //          // NOTE:
     //          break;
     //    }
     //}





      
     int number = 0;
     while ( index < str.length())
     {



         if ( str.charAt(index) < '0' || str.charAt(index) > '9' )
            break;
         int digit = (int) (str.charAt(index) - '0');
         



         // NOTE: -(res*10+digit) < Integer.MIN_VALUE
         if (  negFlag &&  res >  -(Integer.MIN_VALUE+digit)/10  )
               return Integer.MIN_VALUE;
         // NOTE: res*10+digit    > Integer.MAX_VALUE
         else if ( !negFlag && res >  (Integer.MAX_VALUE-digit)/10  )
               return Integer.MAX_VALUE;


       
         number = number*10+digit;
         

        

         index++;



     }









     //return number ;
     return negFalg?-number:number;



     
}
3. Similar Ones
(E) Reverse Integer
(H) Valid Number

[Longest] Longest Common Prefix

1. Example
INSTEAD OF USING A SUBTRING TO MATCH USE INDEX
str[0] as a basis and use append to avoid confusion over using subtring index

s= { "MAU", "MAKAN", "MALAM"}
there are two common prefixes of MAU, which are: "M" and "MA"
Among these, the Longest Common Prefix is "MA" which has a length of 2


2. Implementation
Q1: start from the first word, substring(0,i)i=1~ len
A1; compare it with the rest of string same length,
E.g., M len =1, check i=1 with M and M
MA len =2, check i =2 with MA and MA
MAU len =3, check i=3 wiht MAK and MAL => false
O(string len*array length)


Runtime Error Message:Line 62: java.lang.StringIndexOutOfBoundsException: String index out of range: 1
Last executed input:["cba",""]





Input:["c","c"]
Output:""
Expected:"c"

// Time:O(m*n), Space:O(m), where m is string length and n is numbers of string
public String longestCommonPrefix(String[] strs)
{




    StringBuilder res= new StringBuilder();
    // validate the input
    if ( strs== null || strs.length == 0)
       //return "";
       // NOTE: when loop stop, stringbuilder is what you want
       return res.toString();






    //boolean flag = true;
    //String prefix = new String();
    //for ( int i = 1 ; i <= strs[0].length;i++)
    //{
    //
    //      prefix = strs[0].substring(0,i);
    //      for ( int j =1; j< strs.length; j++)
    //      {
    //             if ( prefix != strs[j].substring(0,i) )
    //             {
    //               flag = false;
    //               break ;
    //             }
    //      }
    //      if (flag == false)
    //        return strs[0].substring(0,i-1);
    //}
    //if (flag == true) 
    //    return strs[0].substring(0,str[0].length);



 

     boolean sameFlag = true;
     int index = 0;




     while ( sameFlag ) 
     {



          for (int i = 0; i < strs.length ;i++)
          {
               if (str[i].length <= index  || strs[i].charAt(index) != str[0])      
               {
                     sameFlag = false;
                     break;
               } 
          }




          if (sameFlag)
          {
               res.append(strs[0].charAt(index));
               index++;
          }       




     }




     return res.toString();




}
3.Similar ones
Longest Series
(H) Longest Valid Parentheses
(M) Longest Palindromic Substring
(M) Longest Substring Without Repeating Characters



(H) Longest Consecutive Sequence

Tuesday, September 8, 2015

[Palindrome][Two Poitner] Valid Palindrome

1. Example

"A man, a plan, a canal: Panama" is a palindrome
"race a car" is not a palindrome

2. Implementation
valid
palindrome
same char
escape special char: continue
l and r
Q1: how to avoid special character?
A1: if there is not  > 'a' or < 'z', we skip the pointer, meaning ++ or --



In Java, the 'int' type is a primitive , whereas the 'Integer' type is an object.

Runtime Error Message:Line 37: java.lang.StringIndexOutOfBoundsException: String index out of range: 2
Last executed input:".,"
//while (!validAphabet(s.charAt(l))) 
 // l++;StringIndexOutOfBoundsException
 //while( !validAlphabet(s.charAt(r))) 
 // r--;
 if ( !isValid(c.charAt(l)) ) 
 { l++; continue; } 
 if ( !isValid(c.charAt(r)) ) 
 { r--; continue; }

//else 
 // NOTE: if return type is required, no need to ELSE
 return false;

// Time:O(string length), Space:O(1)
public boolean isPalindrome(String s)
{
          

  

      // validate the input
      if (s== null || s.length() == 0)
           //return false;
           return true// nothing always palindrome empty to empty.



      int l = 0;
      int r = s.length()-1;
      //for (int i = 0; i < s.length();i++)
      while ( l < r )
      {






           //while (!validAphabet(s.charAt(l)))
             //   l++;
             //while( !validAlphabet(s.charAt(r)))
             //   r--;
             if (  !isValid(c.charAt(l))  )
             {
                  l++;
                  continue;
             }
             if ( !isValid(c.charAt(r))  )
             {
                  r--;
                  continue;
             }







            //if (validAlphbet(s.charAt(l) && validAlphabet(s.charAt(r)) && s.charAt(l) != s.charAt(r)   )
             // NOTE: Uppercase conversion considered
             if (  !isSame(s.charAt(l), s.charAt(r))  )
                 return false;






           l++;               
             r--;




   }



      return true;


     

}
//private boolean validAlphabet(character c)
private boolean validAlphabet(char c)
{

            //if (  (c <= 'Z' || c <= 'z') && (c' >= 'A' || c >= 'a')  ) 
            // NOTE: could be number
            if (  c >= 'a'&& c <='z' || c >='A'&&c<='Z' || c>='0'&&c<='9' )
                     return true;
            //else
            // NOTE: if return type is required, no need to ELSE 
                     return false;  
}

private boolean isSame(char c1, char c2)
{
       if ( c1 >= 'A' && c1 <= 'Z' )
             c1 = (char)( c1- 'A' +'a');
       if ( c2 >= 'A' && c2 <= 'Z') 
             c2 = (char)(c2 - 'A' + 'a');

       return c1== c2;
}
3. Similar Ones
(E) Palindrome Linked List
(H) Shortest Palindrome
(E) Palindrome Number
(M) Palindrome Partitioning