Jerry's Blog

Recording what I learned everyday

View on GitHub


20 October 2019

LeetCode(43) -- 949, 953, 961, 965, 970, 332

by Jerry Zhang

P949. Largest Time for Given Digits (Easy)

给四个数字,放在一个数组里,返回能组成的最大的24小时时间。

我的思路

这四个数字里至少要有一个0,1,2放在第一位。如果用2的话,第二位还必须要有一个小于4的数。 写了半天还有bug,看答案了

答案

class Solution {
    public String largestTimeFromDigits(int[] A) {
        int ans = -1;
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (j != i) {
                    for (int k = 0; k < 4; k++) {
                        if (k != i && k != j) {
                            int l = 6 - i - j - k;
                            int hours = 10 * A[i] + A[j];
                            int minutes = 10 * A[k] + A[l];
                            if (hours < 24 && minutes < 60) {
                                ans = Math.max(ans, hours * 60 + minutes);
                            }
                        }
                    }
                }

            }
        }
        return ans >= 0 ? String.format("%02d:%02d", ans / 60, ans % 60) : "";
    }
}

23% 就是暴力求解,三层for循环.

最优解

class Solution {
    public String largestTimeFromDigits(int[] A) {
        int[] count = new int[10];
        for(int a : A) count[a]++;

        for(int i=2;i>=0;i--){
            if(count[i]>0){
                count[i]--;
                for(int j=9;j>=0;j--){
                    if(count[j]>0 && i*10 + j <=23){
                        count[j]--;
                        for(int k=6;k>=0;k--){
                            if(count[k]>0){
                                count[k]--;
                                for(int l=9;l>=0;l--){
                                    if(count[l]>0 && k*10+l<=59){
                                        return i+""+j+":"+k+""+l;
                                    }
                                }
                                count[k]++;
                            }
                        }
                        count[j]++;
                    }
                }
                count[i]++;
            }
        }
        return "";
    }
}

P953. Verifying an Alien Dictionary (Easy)

在一个外国词典里,26个字母的顺序是不一样的。给一个词典顺序和一组单词,判断它们是否都是按那个顺序排列的。

我的思路

本来想类比ASCII索引的办法,给每个字母也对应一个索引,想了半天没想出来,还想过用binary search,也没成功,最后只得用了hashmap查索引了。

我的代码

public class E_953_VerifyinganAlienDictionary {
    public boolean isAlienSorted(String[] words, String order) {
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < 26; i++) {
            map.put(order.charAt(i), i);
        }
        if (words.length < 2) {
            return true;
        }
        for (int i = 1; i < words.length; i++) {
            String current = words[i];
            String previous = words[i - 1];
            int minLength = Math.min(current.length(), previous.length());
            int j;
            for (j = 0; j < minLength; j++) {
                if (map.get(current.charAt(j)) > map.get(previous.charAt(j))) {
                    break;
                }
                if (map.get(current.charAt(j)) < map.get(previous.charAt(j))) {
                    return false;
                }
            }
            if (j == minLength && previous.length() > minLength) {
                return false;
            }
        }
        return true;
    }
}

41%

最优解

class Solution {
    public boolean isAlienSorted(String[] words, String order) {
        int[] map = new int[26];
        for (int i = 0; i < order.length(); i++) {
            map[order.charAt(i) - 'a'] = i;
        }
        for (int i = 0; i < words.length - 1; i++) {
            if (!compare(words[i], words[i + 1], map)) {
                return false;
            }
        }
        return true;
    }

    public boolean compare(String s1, String s2, int[] map) {
        int l1 = s1.length();
        int l2 = s2.length();
        for (int i = 0, j = 0; i < l1 && j < l2; i++, j++) {
            if (s1.charAt(i) != s2.charAt(j)) {
                if (map[s1.charAt(i) - 'a'] > map[s2.charAt(j) - 'a']) {
                    return false;
                } else {
                    return true;
                }
            }
        }
        if (l1 > l2) return false;
        return true;
    }
}

这是正确答案,用这个。

P961. N-Repeated Element in Size 2N Array (Easy)

在一个长度为2N的数组里,有N+1个不同的数。只有一个数重复了N次。问这个重复了N次的数字是谁。

我的思路

长度为2N,有一个数重复了N次,说明另外N个数,每个数只能出现一次。所以只要发现有重复的,必然是那个重复了N次的数。又因为范围只在0到10000,所以就做了一个长度为10000的布尔型数组,用来记录每个数是否出现过。

我的代码

class Solution {
    public int repeatedNTimes(int[] A) {
        boolean[] map = new boolean[10000];
        for (int i = 0; i < A.length; i++) {
            if (map[A[i]]) {
                return A[i];
            }
            map[A[i]] = true;
        }
        return 0;
    }
}

100%

最优解

class Solution {
    public int repeatedNTimes(int[] A) {
        int i = 0, j = 0, n = A.length;
        while (i == j || A[i] != A[j]) {
            i = (int)(Math.random() * n);
            j = (int)(Math.random() * n);
        }
        return A[i];
    }
}

这个解法很奇特,每次随机找两个数进行比较,如果不相等就接着再找两个,直到相等为止。

P965. Univalued Binary Tree (Easy)

检验一个二叉树的所有节点是否只含有完全相同的值。

我的思路

遍历树,遇到不同的值就返回false.

我的代码

class Solution {
    public boolean isUnivalTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        if (root.left != null && root.val != root.left.val) {
            return false;
        }
        if (root.right != null && root.val != root.right.val) {
            return false;
        }
        return isUnivalTree(root.left) && isUnivalTree(root.right);
    }
}

100%

最优解

class Solution {
    public boolean isUnivalTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        return checkValue(root.left, root.val) && checkValue(root.right, root.val);
    }

    public boolean checkValue(TreeNode node, int value) {
        if (node == null) {
            return true;
        }
        if (node.val == value) {
            return checkValue(node.left, value) && checkValue(node.right, value);
        }
        return false;
    }
}

P970. Powerful Integers (Easy)

两个正整数x,y,如果一个整数可以表示为他们的幂的和,则这个整数叫做powerful。给一个范围,问这个范围内所有powerful的数的集合。

我的思路

依次遍历x的幂和y的幂,嵌套循环,只要他们的和小于bound,就放到set里面。

我的代码

public class E_970_PowerfulIntegers {
    public List<Integer> powerfulIntegers(int x, int y, int bound) {
        HashSet<Integer> set = new HashSet<>();
        int xPower = 1;
        while (xPower < bound) {
            int yPower = 1;
            int sum = xPower + yPower;
            while (sum <= bound) {
                set.add(sum);
                if (y == 1) {
                    break;
                }
                yPower *= y;
                sum = xPower + yPower;
            }
            if (x == 1) {
                break;
            }
            xPower *= x;
        }
        return new ArrayList<>(set);
    }

    public static void main(String[] args) {
        List<Integer> integers = new E_970_PowerfulIntegers().powerfulIntegers(2, 1, 10);
        System.out.println("integers.toString() = " + integers.toString());
    }
}

99%

最优解

class Solution {
    public List<Integer> powerfulIntegers(int x, int y, int bound) {
        List<Integer> list = new LinkedList<>();
        for(int i = 1; i <= bound; i = i * x){
            for(int j = 1; i + j <= bound; j = j * y){
                if (!list.contains(i + j)) {
                    list.add(i + j);
                }
                if(y == 1)  break;
            }
            if(x == 1)  break;
        }
        return list;
    }
}

没用hashset,直接用list的contain方法了。思路差不多,但是代码比我的干净,值得学习。

P332. Reconstruct Itinerary (Medium)

一个数组,其中的每个元素都是一个航班的起始点和到达点。从JFK出发,构建一个路径。如果有多于一个正确的路径,返回字母顺序靠前的。

我的思路

把所有的起始点存到一个HashMap中,对应的value值用一个List表示。DFS来搜索。 有一点思路,代码写完有BUG。

最优解1

class Solution {
    Map<String, PriorityQueue<String>> map = new HashMap<>();
    LinkedList<String> result = new LinkedList<String>();

    public List<String> findItinerary(List<List<String>> tickets) {
        for (List<String> ticket : tickets) {
            if (!map.containsKey(ticket.get(0))) {
                map.put(ticket.get(0), new PriorityQueue<String>());
            }
            map.get(ticket.get(0)).offer(ticket.get(1));
        }

        dfs("JFK");
        return result;
    }

    public void dfs(String s) {
        PriorityQueue<String> pq = map.get(s);

        while (pq != null && !pq.isEmpty()) {
            dfs(pq.poll());
        }

        result.addFirst(s);
    }
}

最优解2

class Solution {
    HashMap<String, PriorityQueue<String>> adjacencyList = new HashMap<String, PriorityQueue<String>>();
    LinkedList<String> result = new LinkedList<String>();

    public List<String> findItinerary(List<List<String>> tickets) {

        for (List<String> ticket: tickets){
            String source = ticket.get(0);
            String destination = ticket.get(1);
            if (adjacencyList.containsKey(source)) {
                adjacencyList.get(source).add(destination);
            } else {
                PriorityQueue<String> queue = new PriorityQueue<String>();
                queue.add(destination);
                adjacencyList.put(source, queue);
            }
        }
        dfs("JFK");
        return result;
    }

    private void dfs(String source) {
        PriorityQueue<String> destinations = adjacencyList.get(source);
        while (destinations != null && destinations.isEmpty() == false) {
            dfs(destinations.poll());
        }
        result.addFirst(source);
    }
}
tags: LeetCode