Sunday, January 6, 2019

801. Minimum Swaps To Make Sequences Increasing


思路比较直接,关键是分析清楚
其实是有三种情况
A[i - 1]   A[i]
B[i - 1]    B[i]

1.先看看是不是可以不swap保持valid
A[i] > A[i - 1] && B[i] > B[i - 1]

2.试试是不是可以swap

32.41 %
class Solution {
    public int minSwap(int[] A, int[] B) {
        int len = A.length;
        int[] swap = new int[len]; // min if we swap A[i]
        int[] noSwap = new int[len]; // min if we don't swap A[i]
        Arrays.fill(swap, Integer.MAX_VALUE);
        Arrays.fill(noSwap, Integer.MAX_VALUE);
        swap[0] = 1;
        noSwap[0] = 0;
        // A[i - 1]  A[i]
        // B[i - 1]  A[i]
       
        for (int i = 1; i < len; i++) {
            if (A[i] > A[i - 1] && B[i] > B[i - 1]){ // good case, no need to swap
                swap[i] = swap[i - 1] + 1;
                noSwap[i] = noSwap[i - 1];
            }
            if (A[i] > B[i - 1] && B[i] > A[i - 1]) { // we can swap
                swap[i] = Math.min(swap[i], noSwap[i - 1] + 1);
                noSwap[i] = Math.min(noSwap[i], swap[i - 1]);
            }
        }
        return Math.min(swap[len - 1], noSwap[len - 1]);
    }
}


[0,3,5,8,9] [2,1,4,6,9]
[0,4,4,5,9] [0,1,6,8,10]
[0,7,8,10,10,11,12,13,19,18] [4,4,5,7,11,14,15,16,17,20]


Saturday, January 5, 2019

791. Custom Sort String




Version #1 Bucket Sort

Time O(S.length() + T.length())

70.74 %
class Solution {
    public String customSortString(String S, String T) {
        StringBuilder sb = new StringBuilder();
        int[] count = new int[26];
        for (int i = 0; i < T.length(); i++) {
            count[T.charAt(i) - 'a']++;
        }
        for (int i = 0; i < S.length(); i++) {
            char c = S.charAt(i);
            while (count[c - 'a']-- > 0) {
                sb.append(c);
            }
        }
        for (int i = 0; i < 26; i++) {
            while (count[i]-- > 0) {
                sb.append((char)(i + 'a'));
            }
        }
        return sb.toString();
    }
}

829. Consecutive Numbers Sum



6.22 %
class Solution {
    public int consecutiveNumbersSum(int N) {
        // N = (a1 + ak)*k/2 = (a1 + a1 + (k - 1)) * k / 2
        // 2N = 2a1 * k + (k - 1) * k
        // 2ka1 = k(k-1) - 2N -> to find a valid a1, we need k(k-1)-2N to be multiple of 2k
        int result = 1;
        for (int k = 2; k * (k - 1) < 2 * N; k++) {
            if ((k * (k - 1) - 2 * N) % (2 * k) == 0) result++;
        }
        return result;
    }
}

Friday, January 4, 2019

860. Lemonade Change

Version #2
48.20 %
class Solution {
    public boolean lemonadeChange(int[] bills) {
int countFive = 0;
int countTen = 0;
for (int bill : bills) {
if (bill == 5) {
countFive++;
} else if (bill == 10) {
countTen++;
countFive--;
} else if (countTen > 0) { // 20
countTen--;
countFive--;
} else {
countFive -= 3;
}
if (countFive < 0) return false;
}
return true;
}
}


Version #1
48.20 %
class Solution {
    public boolean lemonadeChange(int[] bills) {
int countFive = 0;
int countTen = 0;
for (int bill : bills) {
if (bill == 5) {
countFive++;
} else if (bill == 10) {
if (countFive <= 0) return false;
countFive--;
                countTen++;
} else {
if (countTen > 0) {
countTen--;
bill -= 10;
}
while (bill > 5) {
if (countFive <= 0) return false;
countFive--;
bill -= 5;
}
}
}
return true;
}
}

937. Reorder Log Files

Version #2 Compare digits and letters together
class Solution {
    public String[] reorderLogFiles(String[] logs) {
Arrays.sort(logs, (a, b) -> {
String[] aa = a.split(" ", 2);
String[] bb = b.split(" ", 2);
boolean aIsDigit = aa[1].matches("[0-9\\s]+");
boolean bIsDigit = bb[1].matches("[0-9\\s]+");
if (!aIsDigit && !bIsDigit) {
if (aa[1].equals(bb[1])) {
return aa[0].compareTo(bb[0]);
}
return aa[1].compareTo(bb[1]);
}
return (aIsDigit ? 1 : 0) - (bIsDigit ? 1 : 0);
});
return logs;
}
}

Version #1 Bad
3.05 %
class Solution {
    public String[] reorderLogFiles(String[] logs) {
List<String> letterLogs = new ArrayList<>();
List<String> digitLogs = new ArrayList<>();
for (String log : logs) {
int spacer = log.indexOf(" ");
if (spacer == -1 || log.length() <= spacer + 1) continue; //invalid
String str = log.substring(spacer + 1);
if (str.matches("[0-9\\s]+")) {
digitLogs.add(log);
} else {
letterLogs.add(log);
}
}
Collections.sort(letterLogs, (a, b) -> {
String[] aa = a.split(" ", 2);
String[] bb = b.split(" ", 2);
if (aa[1].equals(bb[1])) {
return aa[0].compareTo(bb[0]);
}
return aa[1].compareTo(bb[1]);
});
letterLogs.addAll(digitLogs);
return letterLogs.toArray(new String[letterLogs.size()]);
}
}

Tuesday, January 1, 2019

675. Cut Off Trees for Golf Event

Version #1 BFS

题目是非常straightforward的,主要hard在写起来非常麻烦
我一开始在visit上用 (y << 6) | x对坐标进行hash,避免了visited[rows][cols]但是结果非常的慢,慢出了0%。。。
写了一个bug就是没有考虑start 和end重合的edge case,这种情况如果不特殊考虑的话会return 2 步, 但是实际上需要return 0 部

P.S.这里没有用到从hash = (y << 6) | x里面取x, y的use case, 但是想了一下如果要做的话应该是
mask = (1 << 6) - 1  得到 1000000 - 1 = 111111
x = hash & mask
y = hash >> 6

40.72 %
Without using lambda


25.18 %
class Solution {
    private int rows;
    private int cols;
    public int cutOffTree(List<List<Integer>> forest) {
        this.rows = forest.size();
        this.cols = forest.get(0).size();
        // curr[0] height, curr[1] x, curr[2] y
        List<int[]> trees = new ArrayList<>();
        for (int y = 0; y < rows; y++) {
            for (int x = 0; x < cols; x++) {
                if (forest.get(y).get(x) > 1) {
                    trees.add(new int[]{forest.get(y).get(x), x, y});
                }
            }
        }
        Collections.sort(trees, Comparator.comparing((int[] arr) -> arr[0]));
        int result = 0;
        int[] start = new int[]{0, 0};
        for (int[] end : trees) {
            int step = getDist(start, end, forest);
            // System.out.println(start[1] +  " " + start[2] + " " + end[1] + " " + end[2] + " -> " + step);
            if (step == -1) {
                return -1;
            }
            result += step;
            start[0] = end[1];
            start[1] = end[2];
        }
        return result;
    }
 
    private int[] dx = new int[]{1, 0, -1, 0};
    private int[] dy = new int[]{0, -1, 0, 1};
    // private int mask = (1 << 6) - 1;
    private int getDist(int[] start, int[] end, List<List<Integer>> forest) {
        boolean[][] visited = new boolean[rows][cols];
        if (start[0] == end[1] && start[1] == end[2]) return 0;
        Queue<int[]> que = new LinkedList<>();
        que.offer(start);
        // Set<Integer> visited = new HashSet<>();
        int level = 0;
        while(!que.isEmpty()) {
            level++;
            int size = que.size();
            while (size-- > 0) {
                int[] curr = que.poll();
                for (int i = 0; i < 4; i++) {
                    int nextX = curr[0] + dx[i];
                    int nextY = curr[1] + dy[i];
                    if (nextX == end[1] && nextY == end[2]) return level;
                    if (nextX >= 0 && nextX < cols && nextY >= 0 && nextY < rows
                        && forest.get(nextY).get(nextX) > 0 && !visited[nextY][nextX]) {
                        que.offer(new int[]{nextX, nextY});
                        visited[nextY][nextX] = true;
                    }
                }
            }
        }
        return -1;
    }
}

558. Quad Tree Intersection


奇怪的题,呵呵
点在于求出4个leaf之后需要看这4个leaf是否需要被合并成一个点

33.33 %
class Solution {
    public Node intersect(Node quadTree1, Node quadTree2) {
        if (quadTree1.isLeaf) {
            return quadTree1.val ? quadTree1 : quadTree2;
        }
        if (quadTree2.isLeaf) {
            return quadTree2.val ? quadTree2 : quadTree1;
        }
        quadTree1.topLeft = intersect(quadTree1.topLeft, quadTree2.topLeft);
        quadTree1.topRight = intersect(quadTree1.topRight, quadTree2.topRight);
        quadTree1.bottomLeft = intersect(quadTree1.bottomLeft, quadTree2.bottomLeft);
        quadTree1.bottomRight = intersect(quadTree1.bottomRight, quadTree2.bottomRight);
        // can we combine it into a leaf
        if (quadTree1.topLeft.isLeaf && quadTree1.topRight.isLeaf
            && quadTree1.bottomLeft.isLeaf && quadTree1.bottomRight.isLeaf
            && quadTree1.topLeft.val == quadTree1.topRight.val
            && quadTree1.topLeft.val == quadTree1.bottomLeft.val
            && quadTree1.topLeft.val == quadTree1.bottomRight.val) {
            quadTree1.isLeaf = true;
            quadTree1.val = quadTree1.topLeft.val;
            quadTree1.topLeft = null;
            quadTree1.topRight = null;
            quadTree1.bottomLeft = null;
            quadTree1.bottomRight = null;
        }
        return quadTree1;
    }
}