Sunday, September 29, 2013

74. Search a 2D Matrix ------ M

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

Example 1:

Input:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 3
Output: true

Example 2:

Input:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 13
Output: false
A:
----------------------3rd pass---------------------------------
This is a typical problem of binary search.
You may try to solve this problem by finding the row first and then the column. There is no need to do that. Because of the matrix's special features, the matrix can be considered as a sorted array. Your goal is to find one element in this sorted array by using binary search.


class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if(m==0)
            return false;
        int n = matrix[0].size();        
        int start = 0, end = m*n-1;// treat it as 1 D array
        while(start<=end){
            int mid = start+(end-start)/2;
            if(matrix[mid/n][mid%n] == target)
                return true;
            else if(matrix[mid/n][mid%n] > target){
                end = mid-1;
            }else{
                start = mid+1;
            }
        }
        return false;
    }
};
Mistakes:
1:    low <= high 给写成 low < high
2: 一开始没有用mid,而直接在下面写的,就TMD给忘了 / 2



-------------------------------2nd pass ---------search for row first, then search for col----------------
public class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length, n = matrix[0].length;
        int low = 0, high = m-1;
        while(low<high){
            if(low == high - 1){
                if(matrix[high][0] <=target)
                    low = high;
                break;
            }
            int mid = (low+high)/2;
            if(matrix[mid][0] > target){
                high = mid-1;
            }else{
                low = mid;
            }
        }
        int left = 0, right = n-1;
        while(left<right){ // search the row, indexed by low
            int mid = (left+right)/2;
            if(matrix[low][mid]==target)
                return true;
            if( matrix[low][mid] < target)
                left = mid+1;
            else
                right = mid-1;
        }
        return matrix[low][left]==target;
    }
}

Mistakes:

最后 确定了low和left后,忘了检测该位置是否为target了


--------------------------1st pass-----------------------
最简单的, 就是搜索第一列,找到行, 再搜索该行。
public class Search2DMatrix {
    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length, n = matrix[0].length, i =0;
        while(i+1<Math.min(m,n) && matrix[i][i]<target && matrix[i+1][i+1]<target)
            i++;
        int col = i,row = i;
        if( matrix[row][n-1] >= target ){ // if the last on row i < target, search this row
            while(col+1<n && matrix[row][col+1] <= target)
                col++;
        }else{ // else, linearly search the i_th row
            while(row+1<m && matrix[row+1][col] <= target)
                row++;
        }
        return matrix[row][col]==target;
    }
}

但是上面这个解法是错误的,  自己举个例子想想是为啥??????

Mistakes:
1: int  mid = (low + high) / 2 时, 当low =0., high =1 ----> mid =0  导致死循环
   解决方法,就是在while中加一个if 语句,来检测之。

2:当只有1行的时候, 就没有运行那个check  column的while语句了。


Learned:

Saturday, September 28, 2013

Minimum Window Substring !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Q:
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
For example,
S = "ADOBECODEBANC"
T = "ABC"

Minimum window is "BANC".
Note:
If there is no such window in S that covers all characters in T, return the emtpy string "".
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

A:
之前根据max-crossing subArray的想法,貌似在计算的cross时候,还是不够efficiency.
是不是,可以根据KMP算法呢???


双指针,动态维护一个区间。尾指针不断往后扫,当扫到有一个窗口包含了所有T的字符后,然后再收缩头指针,直到不能再收缩为止。最后记录所有可能的情况中窗口最小的
------------复杂度呢???? 由于被查找的string最多也就265个字符。因此,可以把其看做是constant的, 那么,复杂度就是O(n)了 -------------------


这道题目,最大的注意之处,就是head 和tail指针的 update 方式。不能处理得太粗糙。



Mistakes:
1: 在find cross 的时候,由于low high是inclusive的,因此在计算长度的时候, 要high-low +1
            for (int i = leftStart; i <= rightEnd+1 - curLen; i++) {
2: 题意理解错误。
Input: "a", "aa"
Output: "a"
Expected: ""
从这里来看, 允许重复的字母的。 也必须出现最少相同的次数。

3: 认为最后tail会== S.length() 是正确的, 但是,之间,还依然是inclusive的。  所以,不需要把它当做 exclusive来对待。

4: 哎,犯了一个很SB的错误。 在update  tail 指针的时候,要对每个位置,检查加上后,是否满足match条件,如果是,则退出来。
但是,原本,就随手写了个while (!allFind(count, times) && tail < S.length()) {   这样,逻辑是比较混乱的。


Learned:


-------------第二遍-----------, T中是有计数的,例如S= "a", T = "aa" ,结果应该是false------
 另外,这次,当S超过10000的时候,会有说String index out of 10000的错误。不知道为什么??????????????????????????????????
????????????????
public class Solution {
    public String minWindow(String S, String T) {
        if(S==null || T == null)
            return "";
        HashMap<Character, Integer> origMap = new HashMap<Character, Integer>();
        HashMap<Character, Integer> findMap = new HashMap<Character, Integer>();
        HashMap<Character, Integer> totalMap = new HashMap<Character, Integer>();
        int start = 0,  minStart = S.length(),minEnd = Integer.MAX_VALUE;
        for(int i = 0;i<T.length();i++ ){
            char ch = T.charAt(i);
            if(origMap.containsKey(ch)){
                origMap.put(ch,origMap.get(ch)+1);
            }else{
                origMap.put(ch,1);
            }
        }
        // if a char in S are find in T, if enough apperarance of char, we put it in findMap, otherwise put in totalMap
        for(int i =0;i<S.length();i++){
            char ch = S.charAt(i);
            if(origMap.containsKey(ch) == false)
                continue;
            int count = origMap.get(ch);
            if(findMap.containsKey(ch)){
                findMap.put(ch,findMap.get(ch)+1);
            }else{
                if(totalMap.containsKey(ch)){
                    totalMap.put(ch,totalMap.get(ch)+1);
                }else{
                    totalMap.put(ch,1);
                }
                // check if enough appearance
                if(totalMap.get(ch)>=origMap.get(ch)){
                    findMap.put(ch,totalMap.get(ch));
                    totalMap.remove(ch);
                }
            }
            // check whether we can shrink
            while(findMap.size()==origMap.size()){// find a match, and begin to shrink
                char newChar = S.charAt(start);
                if(origMap.containsKey(newChar)){
                    if(findMap.get(newChar) == origMap.get(newChar)){ // begin to delete
                        totalMap.put(newChar,findMap.get(newChar)-1);
                        if(minEnd - minStart > i - start){
                            minStart = start;
                            minEnd = i;
                        }
                        findMap.remove(newChar);
                    }else{
                        findMap.put(newChar,findMap.get(newChar)-1);
                    }
                }
                start++;
            }
        }
        return minStart==S.length()?"":S.substring(minStart,minEnd+1);
    }
}




---------------3 rd Pass -------------不错不错, 方法虽然是新的idea,但是, 只改了几个拼写错误 , 然后,就一遍过了 --------  哎,Tiger,有进步阿-------------------

IDEA:
用一个HashSet记录是不T 中出现过的字母。 (其实可以用查询MapT,usedMap来代替的,为了清晰,我们这里还是用了)
然后,用一个HashMap, 记录出现字母在T中的次数。 以及发现了的次数。
然后,如果全部发现的话,就把这个对象放进另一个HashMap中缓存起来(当然,如果再次发现的话,也要在这个缓存的Map中更新 nFind。

public class Solution {
    public String minWindow(String S, String T) {
        String result = null;
        // IDEA: use to map to count the strings , if for a char, all are used,
        // Note that duplicates in T are also counted
        // build HashMap for T
        HashMap<Character, Node> mapT = new HashMap<Character, Node>();
        HashSet<Character> set = new HashSet<Character>();
        HashMap<Character, Node> usedMap = new HashMap<Character, Node>();
        for (int i = 0; i < T.length(); i++) {
            char ch = T.charAt(i);
            if (mapT.get(ch) == null) {
                Node tmp = new Node();
                mapT.put(ch, tmp);
                set.add(ch);
            } else {
                mapT.get(ch).count++;
            }
        }
        int begin = 0;// begin of current sub window
        for (int i = 0; i < S.length(); i++) {
            char ch = S.charAt(i);
            if (!set.contains(ch)) { // not in the T String
                continue;
            }

            Node tmp = mapT.get(ch);
            if (tmp == null) {// should be in usedMap,
                tmp = usedMap.get(ch);
                tmp.nFind++;
            } else {// ch appeared in mapT, then we need check
                tmp.nFind++;
                if (tmp.count == tmp.nFind) { // all appearance have been found
                    mapT.remove(ch);
                    usedMap.put(ch, tmp);
                }
            }
            // check whether we should shrink, and from beginning
            while (mapT.isEmpty()) {
                if (result == null || result.length() > i - begin + 1) {
                    result = S.substring(begin, i + 1);
                }
                char tmpChar = S.charAt(begin);
                begin++;
                if (set.contains(tmpChar)) {
                    Node tmpNode = usedMap.get(tmpChar);
                    if (tmpNode.nFind == tmpNode.count) {
                        usedMap.remove(tmpChar);
                        mapT.put(tmpChar, tmpNode);
                    }
                    tmpNode.nFind--;
                }
            }
        }
        return result == null ? "" : result;
    }
}

class Node {
    public int count, nFind;// count if char, and number of find char

    public Node() {
        count = 1;
        nFind = 0;
    }
}








Sort Colors

Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note: You are not suppose to use the library's sort function for this problem.
Example:
Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
Follow up:
  • A rather straight forward solution is a two-pass algorithm using counting sort.
    First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
  • Could you come up with a one-pass algorithm using only constant space?

A:

----------------下面这个解法,有两个错误的,自己看看,错在哪里?------

public class Solution {
    public void sortColors(int[] A) {
        int pre0 = -1,after2 = A.length;// i is pre
        for(int i = 0;i<A.length;i++){
            if(A[i] ==0){
                pre0++;
                swap(A,pre0,i);
            }else if(A[i] == 2){
                after2--;
                swap(A,i,after2);
                i--;
            }
        }
    }
    private void swap(int [] A, int i,int j){
        A[i] ^= A[j];
        A[j] ^= A[i];
        A[i] ^= A[j];
    }
}










Mistakes:

1: swap这个算法,是不对的。  问题就出自,i,j在flag sort里,有可能是相等的。
2: i<A.length 是不对的, 会导致下标越界

------------------4th pass-----------------
public class Solution {
    public void sortColors(int[] A) {
        int pre0 = -1,after2 = A.length;// i is pre
        for(int i = 0;i<after2;i++){
            if(A[i] ==0){
                pre0++;
                swap(A,pre0,i);
            }else if(A[i] == 2){
                after2--;
                swap(A,i,after2);
                i--;
            }
        }
    }
    private void swap(int [] A, int i,int j){
        int tmp = A[i];
        A[i] = A[j];
        A[j] = tmp;
    }
}



---------下面是用one pass 来做的------利用到了2个pointer------
当runner遇到2 的时候, 和后面交换了之后, 要记得把该runner退一步,重新这个从后面刚switch过来的值。 -------而遇到0 的时候,不用退后。


class Solution {
public:
    void sortColors(vector<int>& nums) {
        // i0 is last index of current sorted 0,
        // i2 is (add backward) last added index of 2
        int i0 =-1, i2 = nums.size();
        for(int i =0;i<i2;++i)
        {
            if(nums[i]==0 )
            {
                nums[i] = nums[++i0];// nums[++i0] can be 0 or 1
                nums[i0] = 0;
            }else if(nums[i] ==2){
                nums[i] = nums[--i2];
                nums[i2] = 2;
                --i;
            }
        }
    }
};

Friday, September 27, 2013

77 Combinations

Q:
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
For example,
If n = 4 and k = 2, a solution is:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]
A:
#####递归#############
class Solution:
    def combine(self, n: int, k: int):
        return self.helper(1,n,k)
    
    def helper(self, a: int, b: int, len: int):
        if  b - a + 1 < len or len <= 0:
            return []
        if len == 1:
            return [[i] for i in range(a,b+1)]
        res = []
        for i in range(a,b+1):
            nextList = self.helper(i+1,b, len - 1)
            for tmp in nextList:
                tmp.insert(0, i)
            res.extend(nextList)
        return res

#####循环#############

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        res = []
        for kk in range(1,k+1):
            if kk ==1:
                res = [ [t] for t in range(1,n+1)]
            else:
                newRes = []
                for tmp in res:
                    for lastVal in range(tmp[-1]+1, n+1):
                        newTmp = tmp.copy()
                        newTmp.append(lastVal)
                        newRes.append(newTmp)
                res = newRes
        return res


------4th pass----------是每次分两种情况,
1):   取了第一个数字,
2):   不取第一个数字---------------

public class Solution {
    public List<List<Integer>> combine(int n, int k) {
        return helper(1,n,k);
    }
    private List<List<Integer>> helper(int start,int end,int k){
        List<List<Integer>> ll  = new LinkedList();
        if(k<=0 || k>(end-start+1))
            return ll;
        if(k==1){
            for(int i = start;i<=end;i++){
                List<Integer> l = new LinkedList();
                l.add(i);
                ll.add(l);
            }
            return ll;
        }
        for(List<Integer> tmp : helper(start+1,end,k-1)){
            tmp.add(0,start);
            ll.add(tmp);
        }
        ll.addAll(helper(start+1,end,k));
        return ll;
    }
}




Mistakes:
这道题目的,可能犯得错误,就在于k和start,end的比较。



Learned:
1:    当 all的类型是ArrayList<ArrayList<Integer>>的时候,下面的语句
                all.add(new ArrayList<Integer>(i));
所加入的都是空的ArrayList. 不知道为什么???? 因此要一个个地加。 
一个constructor,当是int 参数时,是给定的initial capacity.
public class Solution {
public ArrayList<ArrayList<Integer>> combine(int n, int k) {
    return combine(1, n, k);
}
public ArrayList<ArrayList<Integer>> combine(int start, int end, int k) {
    ArrayList<ArrayList<Integer>> all = new  ArrayList<ArrayList<Integer>>();
    if(end - start +1 < k  )
        return all;
    // each time, we shrink the size of k
    
    
   if( k == 1){ // 
         for(int i =start; i <= end;i++){
            ArrayList<Integer> al = new  ArrayList<Integer>();
            al.add(i);
            all.add(al);
         }
         return all;
    }else{
         all = combine(start+1,end,k-1);
         for(ArrayList<Integer> al: all) // all with start, 
            al.add(0,start);
        // all without start
         ArrayList<ArrayList<Integer>> newAll = combine(start+1,end,k);
         all.addAll(newAll);
         return all;
    }
}

}

----------------3rd Pass--------------------思路想的一样,但是, 犯了个错误, 就是 在for 循环里, 每次combine了一个 -------------靠,没有犯错,是不自信,在Eclipse中先运行拉下,结果打印的时候, 参数成了那个all了。 白调试了20分钟。

public class Solution {
    public List<List<Integer>> combine(int n, int k) {
        return helper(1,n,k);
    }
    private List<List<Integer>> helper(int start, int end, int k ){
        List<List<Integer>> all = new LinkedList<List<Integer>>();
        if(k==1){
            for(int i=start;i<=end;i++){
                List<Integer> list = new LinkedList<Integer>();
                list.add(i);
                all.add(list);
            }
        }else{
            for(int i =start;i<=end-k+1;i++){
                List<List<Integer>> oneLess = helper(i+1,end,k-1);
                for(List<Integer> al : oneLess)
                    al.add(0,i);
                all.addAll(oneLess);
            }
        }
        return all;
    }
}





Largest Rectangle in Histogram !!!!!!!!!!!!!!!!

Q:
Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.


Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].


The largest rectangle is shown in the shaded area, which has area = 10 unit.
For example,
Given height = [2,1,5,6,2,3],
return 10.

A:
--------------4 rd -------------------依然是用2个stack--------------------
 代码看2nd实现。
犯的错误:
1:当要pop出indexstack之后, 要push进去的,不是当前的i,而是当前最远到达的index(因为之后的,都至少是这个height[i]的高度。
2:  while的时候,没有先检查是否是stack.isEmpty()





 ------------------------1  st ------------------naive way--------------------
经过分析,首先的一个思路,就是,假设某个bar是最低的一个,向左右发展,得到其面积。
哎,也就是说,对for position i,   treat height[i] as the ceiling, calcualte the area.

由于重复计算,代码效率不高。 代码如下

public class Solution {
   public int largestRectangleArea(int[] height) {
        int n = height.length;
        // recording the maximum area , if we assume current position bar is the
        // lowest
        int[] maxAreaHere = new int[n];
        int maxArea = 0;
        for (int i = 0; i < n; i++) {
            // we assume that current bar is the lowest
            // calculate the
            maxAreaHere[i] = height[i];
            // calculate the adjacent left areas,
            int left = i - 1;
            while (left >= 0 && height[left] >= height[i]) {
                maxAreaHere[i] += height[i];
                left--;
            }
            // calculate the adjacent right areas,
            int right = i + 1;
            while (right < n && height[right] >= height[i]) {
                maxAreaHere[i] += height[i];
                right++;
            }
            if (maxArea < maxAreaHere[i]) {
                maxArea = maxAreaHere[i];
            }
        }
        return maxArea;
    }
}

上述解法,会有TLE错误(time Limit exceed )
原因就出在 重复计算上。
网上的解法   GeeksforGeeks       Youtube.                别人的博客
思路如下:
依次加入 每个bar,加入的时候,其与之前的bar们,组成的rectangle的面积。
Solution:
Use Stack to keep track of height and start indexes
Compare current height with previous one

#1: current Larger than previous (top of height stack)
Push current height & index as candidate rectangle start position

#2: current EQUALS previous
Ignore, as largest rectangle will start from previous with same height

#3: current is less than previous
Need keep popping out previous heights, and compute the candidate rectangle with height and width (current index MINUS previous index)
Push the height and index (appropriate position) to stacks

public int largestRectangleArea(int[] height) {
        Stack<Integer> stkH = new Stack<Integer>();// stack recording the height
                                                    // of bar
        Stack<Integer> stkIndex = new Stack<Integer>();// stack recording
                                                        // correspnding index
        int maxArea = 0;
        for (int i = 0; i <  height.length; i++) { // for each length
            // if current bar is higher than previous, push
            if (stkH.isEmpty() || stkH.peek() > height[i]) {
                stkH.push(height[i]);
                stkIndex.push(i);
            } else if (stkH.peek() < height[i]) {
                // if current bar is shorter, we need pop out those longer
                // heights
                // and compute the candidatesrectangle's area and update maxArea
                int lastIndex = 0;// this index to keep track of the last index
                                    // ,which wil lbe repalceing the current
                                    // height inserting
                while (!stkH.isEmpty() && stkH.peek() < height[i]) {
                    // we need compute the size
                    lastIndex = stkIndex.pop();
                    int tmpSize = stkH.pop() * (i - lastIndex);
                    if (maxArea < tmpSize)
                        maxArea = tmpSize;
                }
                // after popping those unqualifed start position, including
                // current index,
                // we add those back , but now, current bar is the lowest from
                // lastIndex ..... i
                stkH.push(height[i]);
                stkIndex.push(lastIndex);
            }
        }
        // after the process, there might still be values in stacks, pop out
        // each other and test size
        while (!stkH.isEmpty()) {
            // we need compute the size, ( from current , down to the most left
            // bar, --- height[0]
            // the width = currentIndex(lat one) - height[i]
            // -------- just imagining we add bar of zero at most right
            int tmpSize = stkH.pop() * (height.length - stkIndex.pop());
            if (maxArea < tmpSize)
                maxArea = tmpSize;
        }
        return maxArea;
    }



Mistakes:


Learned:



------------------------------------------第二遍------------------------------------
思路同上面,那个跟人学的一样

只不过,对于2个stack,我们用一个stack<int[]>代替了。int[] 的长度为2, 第一个是height[i],第二个是index, 表明了,到这个height的之前的,连贯的(大于等于该height的)最远距离。

public class Solution {
      public int largestRectangleArea(int[] height) {
        int maxSize = 0;
        if (height.length <= 0)
            return maxSize;
        // assume just inserted bar is the lowest, and calculate the area
        Stack<int[]> stack = new Stack<int[]>(); // int[] =={height, index}
        for (int i = 0; i < height.length; i++) {
            if (stack.isEmpty() || stack.peek()[0] < height[i]) {
                int[] tmp = { height[i], i };
                stack.push(tmp);
            } else if (stack.peek()[0] >  height[i]) {
                int lastIndexGreaterThanCurrent = i; // greater than height[i]
                while (!stack.isEmpty() && stack.peek()[0] > height[i]) {
                    // pop the curent stack
                    int[] tmp = stack.pop();
                    lastIndexGreaterThanCurrent = tmp[1];
                    int curSize = tmp[0] * (i - tmp[1] );
                    maxSize = Math.max(maxSize, curSize);
                }
                // push the current value
                int[] tmp = { height[i], lastIndexGreaterThanCurrent };
                stack.push(tmp);
            }
        }
        // deal with the case that stack is not empty
        while (!stack.isEmpty()) {
            int[] tmp = stack.pop();
            int curSize = tmp[0] * (height.length - tmp[1]);
            maxSize = Math.max(maxSize, curSize);
        }
        return maxSize;
    }
}

-------------------------第三遍-----------------------
再一次强调,  当现在的height[i]的值更小的时候,  我们要计算的,是在它之前的所有的面积, 而不是包括它的面积。!!!!!!!!!!!!!!!1
Tiger,   再仔细看看, 那几行代码吧。。。。





Mistakes:
1:  两个index相减, 其长度应该是要加1 的。 哎,丢人,这么SB的错误
2:刚开始的这个思想根本就是不对的。 当stack.peek() < height[i]的时候,我们应该计算的,是对于所有大于height[i]这个高度的 和

Learned:


86. Partition List ------------M

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

Example:

Input: head = 1->4->3->2->5->2, x = 3
Output: 1->2->2->4->3->5
A:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode less(0);
        ListNode greater(0);
        ListNode *pl = &less;
        ListNode *pg = &greater;
        
        while(head){
            ListNode *ptr = head;
            head = head->next;
            ptr->next = nullptr;
            if(ptr->val < x){
                pl->next = ptr;
                pl = ptr;
            }else{
                pg->next = ptr;
                pg = ptr;
            }
        }
        pl->next = greater.next;
        return less.next;
    }
};
Mistakes:
1: detach 一个node, 并将之放到新的list的tail上时,, 忘记把它的next节点设为null

2: 由于命名的原因(更主要的是,开始没有思考清楚,导致) 最后把tail.next = header 了。


 --------第二遍, ---思路同上----------
 Mistakes:
1:    lowerTail.next = higherHeader.next;  刚开始,SB了,写成lowerHeader.next = higherHeader.next;


--------------3rd Pas ------------------依然是用2个header。 但是,没有用original header,而直接用head 来跑。----------------------

public class Solution {
    public ListNode partition(ListNode head, int x) {
        ListNode h1 = new ListNode(0);
        ListNode h2 = new ListNode(0);
        ListNode tail1 = h1,tail2 = h2;
        while(head!= null){
            ListNode tmp = head;
            head = head.next;
            
            tmp.next = null;
            if(tmp.val<x){
                tail1.next = tmp;
                tail1 = tail1.next;
            }else{
                tail2.next = tmp;
                tail2 = tail2.next;
            }
        }
        // attach h2  to the end of h1
        tail1.next = h2.next;
        return h1.next;
    }
}

Error:
 while(head!= null){
            ListNode tmp = head;
            tmp.next = null;
            head = head.next;
          
这里,这样写,顺序是不对的。 应该先 head = head.next之后,再把tmp的指针置null

Decode Ways

Q:
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12).
The number of ways decoding "12" is 2.

A:
 -------------------------------DP ----------------------------

class Solution {
public:
    int numDecodings(string s) {
        int n = s.length();
        vector<int> count(n+1, 0);
        count[0] = 1; // so as to avoid checking boundary
        for(int i =0;i < n;++i)
        {
            if(s[i]>='1' && s[i]<='9')
                count[i+1] = count[i];
            if(i>0)
            {
                string s2 = s.substr(i-1,2); // substr(startIndex, length)
                int val = stoi(s2);
                if(val>=10 && val <=26 )
                {
                    count[i+1]  +=  count[i-1];
                }
            }
        }
        return count[n];
    }
};




Mistakes:
1:  哎,一开始,竟然看成是输入为ABC类了。Tiger,你得多SB啊~~~
光为了简洁代码了,输入都没有检测,哎~~~~~~~

2: 当i-2<0的时候, 应该还是 +=  而不是简单的 =1
教训啊, 不要为了狗屁不如的代码简洁。 那个不重要,  首先要保证正确。

3: valid (2个char )的时候, 首先要看,第一个是否是0, 如果是, 就不对。
-------------------------3 rd Pass---------------------思路同上------------------------

代码打了很多补丁,就不写到这里了。
Error:
1:开始没有考虑检查输入是否valid的情况, 例如输入为”0“
2:第一稿的时候,直很一厢情愿地,认为不会有"10"的输入, 或者说,不会有0这个数字。 艹,太SB 了。






Scramble String

Q:
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
    great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
           / \
          a   t
To scramble the string, we may choose any non-leaf node and swap its two children.
For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".
    rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
           / \
          a   t
We say that "rgeat" is a scrambled string of "great".
Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".
    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a
We say that "rgtae" is a scrambled string of "great".
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

A:
 首先,我们想到的是递归调用
代码如下:
public class Solution {
       public boolean isScramble(String s1, String s2) {
        // idea: assume s1 is original string , and s2 is the scrambled one
        // if scrambled, it must be that it is first k letters of s2 is the
        // scramble of first k letters of s1
        if(s1.length() != s2.length())
            return false;
        if(s1.length() == 1){
            return s1.charAt(0) == s2.charAt(0);
        }
        for(int i = 1;i< s1.length()-1; i++){ // i is the position , belongs to left part
            boolean left1 = isScramble(s1.substring(0,i+1),s2.substring(0,i+1));
            boolean right1 = isScramble(s1.substring(i+1),s2.substring(i+1));
            
            boolean left2 = isScramble(s1.substring(0,i+1),s2.substring(s2.length() - i));
            boolean right2 = isScramble(s1.substring(s1.length() - i),s2.substring(0,i+1));
            
            if(left1 && right1 || left2 && right2)
                return true;
        }
        return false;
       }
}

当然,结果是太慢 TLE


-----------下面是非递归的方法。  ------------------


主要错误在于: 对每个position, 我们有两个选择, 或者在这个点scramble或者在这里继续向两边分。

public class ScrambleString {
    public boolean isScramble(String s1, String s2) {
        // idea: assume s1 is original string , and s2 is the scrambled one
        // if scrambled, it must be that it is first k letters of s2 is the
        // scramble of first k letters of s1
        if (s1.length() != s2.length())
            return false;
        if (s1.length() == 1) { // s2.length == 1
            if (s1.equals(s2)) {
                return true;
            } else {
                return false;
            }
        }
        // NOW string length >= 1
        int n = s1.length();
        // for the first k letters, check it is the left scramble.
        if (s1.equals(s2)) {
            return true;
        }
        // find a split at split index i
        // At position i, we have two choice,
        // 1) permute here,
        // 2) continue split at i, left to left, right to right
        for (int i = 1; i < s1.length(); i++) {// left and right should not
                                                // be empty
            // CASE 1: we scramble at this position
            // if left of s1 == right of s2, they are the same, we can return
            // true
            String s1LeftI = s1.substring(0, i);
            String s1AfterI = s1.substring( i);
            // if left of s1 is the same with right of s2, and vice versa
            String s2MatchLeftS1 = s2.substring(n - i);
            String s2MatchRightS1 = s2.substring(0, n - i);
            if (isPermuation(s1LeftI, s2MatchLeftS1)&& isPermuation(s1AfterI, s2MatchRightS1)) {
                boolean left = isScramble(s1LeftI, s2MatchLeftS1);
                boolean right = isScramble(s1AfterI, s2MatchRightS1);
                if (left && right) {
                    return true;
                }
            }
            String s2LeftI = s2.substring(0, i);
            String s2AfterI = s2.substring( i);
            if (isPermuation(s1LeftI, s2LeftI)&& isPermuation(s1AfterI, s2AfterI)) {
                // if left of s1 is permuation of ( left of s2), and
                boolean left = isScramble(s1LeftI,
                        s2LeftI);
                boolean right = isScramble(s1AfterI, s2AfterI);
                if (left && right) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isPermuation(String str1, String str2) {
        char[] a = str1.toCharArray();
        char[] b = str2.toCharArray();
        Arrays.sort(a);
        Arrays.sort(b);
        return Arrays.equals(a,b);
    }
}


Mistakes:
1: 光顾的左右分区了,没有考虑,交换过来的情况。
2: 自己的命名挺ugly的。呵呵

Learned:
1: java 中, Arrays.sort()是基于int (或者double)类型的   quicksort实现。
因此,char [] 也可以直接调用
--------------------------------第二遍-----------思想同上--------
public class Solution {
 public boolean isScramble(String s1, String s2) {
        // idea: assume s1 is original string , and s2 is the scrambled one
        // if scrambled, it must be that it is first k letters of s2 is the
        // scramble of first k letters of s1
        if (s1.length() != s2.length())
            return false;
        if (s1.length() == 1) {
            return s1.charAt(0) == s2.charAt(0);
        }
        char[] ch1 = s1.toCharArray();
        char[] ch2 = s2.toCharArray();
        Arrays.sort(ch1);
        Arrays.sort(ch2);
        // check whether ch1 == ch2
        if(Arrays.equals(ch1,ch2)==false)
            return false;
        // now, characters are the same, we check their scrambling
        for (int leftLen = 1; leftLen < s1.length(); leftLen++) { // i is the length of left
                                                    // part of s1
            String leftS1 = s1.substring(0, leftLen );
            String rightS1 = s1.substring(leftLen );
            // if left i part match s1
            String leftS2 = s2.substring(0, leftLen);
            String rightS2 = s2.substring(leftLen );

            if (isScramble(leftS1, leftS2) && isScramble(rightS1, rightS2))
                return true;

            // now test case 2, where s2 is scrambled to the right part
            String s2MatchLeftS1 = s2.substring(s2.length() - leftLen);
            String s2MatchRightS2 = s2.substring(0, s2.length() - leftLen);

            if (isScramble(leftS1, s2MatchLeftS1) && isScramble(rightS1, s2MatchRightS2))
                return true;
        }
        return false;
    }
}
------------------------------3 rd -----------------思路同第二遍----------------
Error:
1:      很傻比, 不知道,s1的左边要跟s2的右边比较,  反而去左边和左边比较,右边和右边比较去了。  哎,SB
2:     脑子被驴踢了,哎,竟然能犯这个SB 错误。  自己看看吧。 为什么下面这样写不对。

import java.util.Arrays;

public class Solution {
    public boolean isScramble(String s1, String s2) {
        // use recursive idea, but instead of trying every possible chars,
        if (s1.length() != s2.length())
            return false;
        int n = s1.length();
        if (n == 0 || s1.equals(s2))
            return true;
        // now beginning and end is not equal, we need do left right matching
        for (int i = 1; i < n; i++) {
            String s1Left = s1.substring(0, i);
            String s1Right = s1.substring(i);

            // test whether left of s1 equals left of s2
            String s2Left = s2.substring(0, i);
            String s2Right = s2.substring(i);
            if (isEqualAfterSort(s1Left, s2Left))
                return isScramble(s1Left, s2Left)
                        && isScramble(s1Right, s2Right);

            s2Left = s2.substring(0, n - i);
            s2Right = s2.substring(n - i);
            // if left of s1 equals to right of s2
            if (isEqualAfterSort(s1Left, s2Right))
                return isScramble(s1Left, s2Right)
                        && isScramble(s1Right, s2Left);
        }
        return false;
    }

    private boolean isEqualAfterSort(String str1, String str2) {
        char[] arr1 = str1.toCharArray();
        char[] arr2 = str2.toCharArray();
        Arrays.sort(arr1);
        Arrays.sort(arr2);
        String ss1 = new String(arr1);
        String ss2 = new String(arr2);
        return ss1.equals(ss2);
    }
}










揭示错误2:  因为,即使两个sort后是一样的,但依然不能保证是scramble的。 因此,不能直接返回结果, 而应该是match之后,如果是true,才能返回

Merge Sorted Array

Q:
Given two sorted integer arrays A and B, merge B into A as one sorted array.
Note:
You may assume that A has enough space to hold additional elements from B. The number of elements initialized in A and B are m and n respectively.

A:

-----------------------2nd pass ---------------------------

public class Solution { 
    public void merge(int A[], int m, int B[], int n) {
        int iA = m-1,iB=n-1;
        while(iB>=0){
            if(iA>=0 && A[iA] > B[iB]){
                A[iA+iB+1] = A[iA];
                iA--;
            }else{
                A[iA+iB+1] = B[iB];
                iB--;
            }
        }
    }
}

-------------------1st pass----------------------------

public class Solution {
    public void merge(int A[], int m, int B[], int n) {
        int pA = m-1;
        int pB = n-1;
        while( pB >= 0 && pA>=0){
            if(A[pA] >= B[pB] ){
                A[pA+pB+1] = A[pA];
                pA--;
            }else{
                A[pA+pB+1] = B[pB];
                pB--;
            }
        }
        // test if pA <0, then we copy the rest of B
        if(pB>=0){
            for(int i =pB;i>=0;i--){
                A[i]=B[i];
            }
        }
        
    }
}

Unique Paths

Q:
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?


Above is a 3 x 7 grid. How many possible unique paths are there?
Note: m and n will be at most 100.


A:

另外,其实,可以免掉recursive调用,直接在数组上来计算的。
----第二遍  Iterative way, using 2D array----
public class Solution {
    public int uniquePaths(int m, int n) {
        if(m<=1||n<=1)
            return 1;
        int[][] A = new int[m][n];
        Arrays.fill(A[0],1);
        for(int i =1;i<m;i++)
            for(int j =0;j<n;j++)
                A[i][j] = j==0?1:A[i-1][j]+A[i][j-1];
        return A[m-1][n-1];
    }
}


 利用一维数组  using 1D array 

public class Solution {
    public int uniquePaths(int m, int n) {
        int[] A = new int[n];
        Arrays.fill(A,1);
        for(int i =1;i<m;i++)
            for(int j =1;j<n;j++)
                A[j] += A[j-1];
        return A[n-1];
    }
}
 

第一个是recursively  调用,同时用一个数组,来记录已经用过的调用。


public class UniquePaths {
    public int uniquePaths(int m, int n) {
        // DP
        int[][] pathNum = new int[m + 1][n + 1];// ignore the 0 row and col
        return recursivePath(pathNum, m, n);

    }

    private int recursivePath(int[][] pathNum, int row, int col) {
        if (pathNum[row][col] != 0) {
            return pathNum[row][col];
        } else {
            // else ,we need calculate them
            if (row == 1 && col == 1) {
                pathNum[1][1] = 1;
                return 1;
            }
            // now we can reduce their case
            int stepDown = 0;
            if (row >= 2) {
                stepDown = recursivePath(pathNum, row - 1, col);
                pathNum[row - 1][col] = stepDown;
            }
            int stepRight = 0;
            if (col >= 2) {
                stepRight = recursivePath(pathNum, row, col - 1);
                pathNum[row][col - 1] = stepRight;
            }
            return stepRight + stepDown;
        }
    }
}


89. Gray Code ---M

Q:
The gray code is a binary numeral system where two successive values differ in only one bit.
Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.
For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
00 - 0
01 - 1
11 - 3
10 - 2
Note:
For a given n, a gray code sequence is not uniquely defined.
For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.
For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.
A:     递归调用而已
class Solution {
public:
    vector<int> grayCode(int n) {        
        if(n==0)
            return vector<int>{0};        
        auto sub = grayCode(n-1);
        int subSize = sub.size();
        for(int i =subSize -1 ; i>=0; i--){
            sub.push_back(sub[i] + pow(2,n-1));
        }
        return sub;
    }
};




Error: 
 1: 刚开始,base情况设为了n == 1
2: 后面要加的时候,没有逆序



-------------------第二遍,迭代,基于binary的一个个位置的从0变1, 就把之前的list都copy下来,再0变1.  -----------
public class Solution {
    public List<Integer> grayCode(int n) {
        List<Integer> al = new LinkedList();
        al.add(0);
        int start = 0;
        for(int i =0;i<n;i++){
            List<Integer> copyAL = new LinkedList(al);
            for(int j =copyAL.size()-1;j>=0;j--)
                al.add( (1<<i) +copyAL.get(j));
        }
        return al;
    }
}


Mistakes:
1: curList  必须先initialize (刚开始,是在n ==0, 和n==1的时候,initilize了,但是, 其余的情况,就忘了initialize了)

2:输入为0 的时候,输入应该是 【0】, 而不是空的----------》这个是应该面试的时候问明白。
0
Output: []
Expected: [0]


Learned:
1:  直接把一个数组,转换成String是不太容易的。 结果会有【】 出现。 例如下面:
        int[] iArray= {2,3};
        String str = Arrays.toString(tmp);
        System.out.println(str);
因此,要把“,” 去掉,  还有前后的[] 也要去掉。
  • String temp = Arrays.toString(iArray).replace(", ", " ");
  • String encoded = temp.substring(1, temp.length()-2);


  • Add Binary

    Q:
    Given two binary strings, return their sum (also a binary string).
    For example,
    a = "11"
    b = "1"
    Return "100".

    A:
    就是用个StringBuffer , 来保存并计算

    public class Solution {
        public String addBinary(String a, String b) {
            // make them backward
            StringBuffer bufA = new StringBuffer(a);
            StringBuffer bufB = new StringBuffer(b);
            StringBuffer bufC = new StringBuffer();
            bufA.reverse();
            bufB.reverse();
            int m = a.length(), n = b.length();
            int carry =0;
            for(int i=0;i<Math.max(m,n);i++){
                int c =0,d=0;
                if(i<m)
                    c=bufA.charAt(i)-'0';
                if(i<n)
                    d = bufB.charAt(i)-'0';
                bufC.append( (c+d+carry)%2);
                carry = (c+d+carry)/2;
            }
            if(carry ==1)
                bufC.append(1);
            return bufC.reverse().toString();
        }
    }
    

    ------------------------第二遍---------思路一样---------------
    public class Solution {
        public String addBinary(String a, String b) {
            // make two string of the same length
            // assume a is longer
            if(a.length()<b.length()){
                String tmp = b;
                b = a;
                a = tmp;
            }
            // NOW, str2 is shorter
            StringBuffer buf = new StringBuffer(b);
            for(int i =0;i<a.length()-b.length();i++){
                buf.insert(0,'0');
            }
            b = buf.toString();
            // now a and b are of the same length;
            boolean carry = false; // first carry is zero
            StringBuffer result = new StringBuffer();
            for(int i =a.length()-1;i>=0 ; i--){
                boolean aa = a.charAt(i) == '1';
                boolean bb = b.charAt(i) == '1';
                if( logicalXOR(logicalXOR(aa,bb),carry)  ){
                    result.insert(0,1);
                }else{
                    result.insert(0,0);
                }
                carry = aa&&bb || aa&&carry || bb&&carry;
            }
            if(carry){
                result.insert(0,1);
            }
            return result.toString();
        }
        private static boolean logicalXOR(boolean x, boolean y) {
            return ( ( x || y ) && ! ( x && y ) );
        }
    }
    


    Learned:
    1: StringBuffer 有个函数,是setCharAt(int index, char ch);
    2:  计算residue 可以直接用 a^b即可。  (第一次,是用了!(a^b)了, 哎

     -----------------------3 rd Pass ----------------思路同上,更加简洁-----------------
    public class Solution {
        public String addBinary(String a, String b) {
            StringBuffer buf = new StringBuffer();
            int carry = 0;
            int m = a.length();
            int n = b.length();
            for (int i = 0; i < Math.max(m, n); i++) {
                int ai = (i >= m) ? 0 : a.charAt(m-1-i) - '0';
                int bi = (i >= n) ? 0 : b.charAt(n-1-i) - '0';
                int ci = (ai ^ bi) ^ carry;
                buf.insert(0, ci);
                carry = (ai + bi + carry) / 2;
            }
            if (carry == 1)
                buf.insert(0, '1');
            return buf.toString();
        }
    }
    




    Thursday, September 26, 2013

    Word Search -M

    Given a 2D board and a word, find if the word exists in the grid.
    The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.
    Example:
    board =
    [
      ['A','B','C','E'],
      ['S','F','C','S'],
      ['A','D','E','E']
    ]
    
    Given word = "ABCCED", return true.
    Given word = "SEE", return true.
    Given word = "ABCB", return false.

    A:

     ----------------------------------  3 rd pass ,  用一个2D array 记录是否visit过---------- 然后就是简单的dfs了----------------和第二遍一样,但是,没有这里,检测了输入m,n是否为0 的情况,因此,多写了几行。------------
    class Solution {
    public:
        bool exist(vector<vector<char>>& board, string word) {
            int m = board.size(), n = board[0].size();
            vector<vector<bool>> flags;
            for(int i =0;i<m;++i)
            {
                vector<bool> tmp(n,false);
                flags.push_back(tmp);
            }
            for(int i =0;i<m;++i)
                for(int j=0; j<n;++j)
                    if(dfs(board, flags, word,0, i,j))
                        return true;
            return false;
        }
    private:
        bool dfs(vector<vector<char>>& board, vector<vector<bool>> & A, string word, int index,int i, int j)
        {
            int m = A.size(), n = A[0].size();
            if(board[i][j] == word[index] && A[i][j]==false)
            {
                A[i][j] = true;
                if(++index >= word.length()) // if board==[[a]], following 4 cannot go further
                    return true;
                
                if(i>0 && dfs(board, A, word, index,i-1,j)) // go up
                    return true;
                
                if(i+1<m && dfs(board, A, word, index, i+1, j)) // go down
                    return true;
                
                if(j>0 && dfs(board, A, word, index, i, j-1)) // go left
                    return true;
                
                if(j+1<n && dfs(board, A, word, index, i, j+1)) // go right
                    return true;
                
                A[i][j] = false;
            }
            return false;
        }
    };

    错误:

    在dfs中,我们已经假设了word不为空,就需要在match当前char之后,再看现在是否start 位置还没出界-------------------






    -------------------------------第二遍   ---- 思路同上,但是没有用Stack-------------------
    就是设立了一个2D的标识。记录是否被存下。

    public class Solution {
        public boolean exist(char[][] board, String word) {
            if(board == null || word == null || board.length==0|| board[0].length == 0)
                return false;
            int m = board.length,n = board[0].length;
            boolean[][] A = new boolean[m][n];
            for(int i =0;i<m;i++){
                for(int j =0; j<n;j++)
                    if(helper(board,A,i,j,word))
                        return true;
            }
            return false;
        }
        private boolean helper(char[][] board,boolean[][] A, int i ,int j , String word){
            if(word.length()==0)
                return true;
            if(i<0||i>=board.length || j<0 || j>= board[0].length)
                return false;
            if(A[i][j] == false && word.charAt(0) == board[i][j]){
                A[i][j] = true; // set the signal
                String tmp = word.substring(1);
                if( helper(board,A,i-1,j,tmp) ||helper(board,A,i+1,j,tmp) || helper(board,A,i,j-1,tmp) || helper(board,A,i,j+1,tmp) )
                    return true;
                A[i][j] = false;
            }
            return false;
        }
    }
    
    

    ----------------错误---------------

    开头的这句话
    boolean[][] hasVisited = new boolean[board.length][board[0].length];
    一开始,给写到 双重循环里面去了。导致超时,哎, 一晚上,就因为这个被stuck住, 都没干别的。 郁闷~~~~~~~~不值得啊




     ------------------------------------------- 1 st  pass ---------------------------------------------------------------
    增强的 DFS ,
    思路就是,通过另一个visitedBoard来记录该节点是否所有的neighbor都被visited 过。如果没有,则增加一个,如果有。 则pop出来该节点。并将其父节点(stack.peak()) 的visitBoard 的数量增加1.
    -----------------
    一个关键的问题就是:我们dfs的时候,设置了停止条件是: start>word.length();  但是这样是不对的。
    因为,有可能我们的下标没有可能出界的。例如输入时“s”,"s"。
    因此,我们要检测是否是最后一个char






    Mistakes:
    1:   findStringIndex的考虑的时候, 例如当问题中给出的例子,”ABCB“的时候, 当找到C的时候, findStringIndex 的值是3了, 而,在我们别的变量里面,都是index, 而不是match的数量,因此,我们这里应该是2的。 ------------------------------哎,你个糊涂蛋,------------
                         if( lastFindCharIndex >= word.length() -1){// if match the last char
                            return true; // we just find the whole word
                        }
    你这里,是考虑的当已经找到了最后一个的情况,   然后,我们这时候,在下面的四种情况中,是 加了1 的,      那么,就word.length() 就不应该减一啊。
    -------------哦, 当初想减一,是考虑到,后面的4种情况监测的时候,  要加1 啊
    晕,你SB,  上面全错了, 那样写是对的,只是因为,题目要求 may NOT  use the same letter more than once. --------------------看题不谨慎啊!!!!!!!!
    2:在利用tmpBoard的时候,忘了把第一个字母全部变成neverUsedChar,  导致输入{"aa"} "aaa"的时候,结果是find。

    3: 当一条路走不通的时候,应该把走过的路,都回溯成原来的样子, 以待别走法。

    4: 不能用BFS, 那样的话, 就会先把周围match的点的颜色先该了。
    5: 自己还是因为,对DFS的理解不够深入导致,回去多看看类似的DFS,BFS的 题目吧。


    Learned:
    1: ArrayList<int[]> firstIndexes = new ArrayList<int[]>();  这样是可以的, 而不是非得用Integer 取代int. (自己是受以前的代码的影响)
    2:




    Wednesday, September 25, 2013

    90. Subsets II ---------M ~~~~~~~

    Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).

    Note: The solution set must not contain duplicate subsets.

    Example:

    Input: [1,2,2]
    Output:
    [
      [2],
      [1],
      [1,2,2],
      [2,2],
      [1,2],
      []
    ]
    A:
    之前的思路,很僵化,迂腐。 还是局限于问题I, 先找到,然后消除重复。
    但,实际上,我们可以对重复的元素,多进行分析。得到如下 方法。
    先sort( S) , ,then for each distinct value in S, say  val,  we find different sets of  permutation of val,
    if val is single valued, it has only one permutation
    if val has multiple value, we generate them and adding on back separately.
    for example, val is S = [1 ,2,2], when adding value 2, we first generate all permutation of [2,2],
    
    
    class Solution {
    public:
        vector<vector<int>> subsetsWithDup(vector<int>& nums) {
            unordered_map<int,int> map;
            for(auto v:nums)
                map[v] += 1;
            
            vector<vector<int>> res{vector<int>()};
            auto iter = map.begin();
            while(iter != map.end()){
                int curSubsetSize = res.size();
                for(int k =1;k<=iter->second;k++){ // for how many time, we append this new value
                    for(int i =0;i<curSubsetSize;i++){
                        vector<int> newLine(res[i]);
                        for(int j = 0;j<k;j++)
                            newLine.push_back(iter->first);
                        res.push_back(newLine);
                    }
                }
                iter++;
            }
            return res;
        }
    };

    Mistakes:
    1: copyArrayList()加了start 参数后,在函数里面,忘了把从0开始,改成从start开始。

    Learned:
    中心思想就是,把相同的数字,当做一组来看待。然后,循环加入。

    ----------------第二遍,  思路同上-- 只不过, 因为对new ArrayList<Integer>(al) 命令,给出的是一个新的对象,而不是像all那样,是一个引用。 所以,我们可以节省一些空间。

    public class Solution {
        public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] S) {
            Arrays.sort(S);
           ArrayList<ArrayList<Integer>> all = new ArrayList<ArrayList<Integer>>();
            all.add(new ArrayList<Integer>());
            for(int i=0;i<S.length;i++){
                int newVal = S[i];
                int count =1;
                while(i+1<S.length && S[i+1] == S[i]){
                    i++;
                    count++;
                }
                int origLength = all.size();
                for(int j = 0; j< origLength;j++   ){ // for each original all  of 
                    for(int len = 1; len<=count; len++ ){ // for each permutation of sequencial "333"
                    // add len number of ewVal at the end of newAll
                        ArrayList<Integer> newAll = new ArrayList<Integer>(all.get(j));
                        for(int k =0; k< len; k++)
                            newAll.add(newVal);   
                        all.add(newAll);
                    }
                } // end of for loop for each line of all
            } // end of for loop for each S[i]
            return all;
        }
    }
    


    ---------------------- 3 rd ------------非要用 递归,结果超过30行了--------------------

    public class Solution {
        public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] S) {
            Arrays.sort(S);
            return subsets(S, 0);
        }
    
        private ArrayList<ArrayList<Integer>> subsets(int[] S, int start) {
            ArrayList<ArrayList<Integer>> all = new ArrayList<ArrayList<Integer>>();
            if (start == S.length) {
                ArrayList<Integer> al = new ArrayList<Integer>();
                all.add(al);
                return all;
            }
            int count = 1;
            // find till the next one
            while (start < S.length - 1 && S[start] == S[start + 1]) {
                count++;
                start++;
            }
            ArrayList<ArrayList<Integer>> lastAll = subsets(S, start + 1);
            for (int j = 1; j <= count; j++)
                all.addAll(copyAndAdd(lastAll, S[start],j));
            all.addAll(lastAll);
            return all;
        }
    
        private ArrayList<ArrayList<Integer>> copyAndAdd(
                ArrayList<ArrayList<Integer>> all, int val,int count) {
            ArrayList<ArrayList<Integer>> newAll = new ArrayList<ArrayList<Integer>>();
            for (ArrayList<Integer> al : all) {
                ArrayList<Integer> newAl = new ArrayList<Integer>();
                for (int i = 0; i < al.size(); i++)
                    newAl.add(al.get(i));
                for(int i =0;i<count;i++)
                    newAl.add(0, val);
                newAll.add(newAl);
            }
            return newAll;
        }
    }
    



    Subsets

    Given a set of distinct integers, nums, return all possible subsets (the power set).
    Note: The solution set must not contain duplicate subsets.
    Example:
    Input: nums = [1,2,3]
    Output:
    [
      [3],
      [1],
      [2],
      [1,2,3],
      [1,3],
      [2,3],
      [1,2],
      []
    ]

    A:

    class Solution {
    public:
        vector<vector<int>> subsets(vector<int>& nums) {
            vector<vector<int>> res;
            vector<int> tmp;
            res.push_back(tmp);
            
            for(auto v : nums)
            {
                int n = res.size();
                for(int i =0;i<n;++i)
                {
                    vector<int> tmp = res[i];
                    tmp.push_back(v);
                    res.push_back(tmp);
                }
            }
            return res;
        }
    };

    Mistakes: