Jerry's Blog

Recording what I learned everyday

View on GitHub


21 September 2019

LeetCode(14) -- 500, 501,

by Jerry Zhang

P500. Keyboard Row (Easy)

我们知道,美式键盘的字母有三行。给一个字符串数组,找出那些能用键盘上一行按键就能打出来的单词。

Input: ["Hello", "Alaska", "Dad", "Peace"]
Output: ["Alaska", "Dad"]
因为只需要第二行就能打出来

我的思路

把所有的字母对应的行数存到一个数组里,用ASCII码作为索引,这样只要给一个字母就能立即找到它在第几行,如果都相等就返回到结果集中。

从大写字母A(65)到小写字母z(122)一共有58个字符,除了26个字母,大小写52个字母外,中间还有6个其他的字符。

我的代码

public class E_500_KeyboardRow {
    public String[] findWords(String[] words) {
        int[] rowNumbers = new int[58];
        rowNumbers[0] = 2; rowNumbers[1] = 3; rowNumbers[2] = 3; rowNumbers[3] = 2; rowNumbers[4] = 1;
        rowNumbers[5] = 2; rowNumbers[6] = 2; rowNumbers[7] = 2; rowNumbers[8] = 1; rowNumbers[9] = 2;
        rowNumbers[10] = 2; rowNumbers[11] = 2; rowNumbers[12] = 3; rowNumbers[13] = 3; rowNumbers[14] = 1;
        rowNumbers[15] = 1; rowNumbers[16] = 1; rowNumbers[17] = 1; rowNumbers[18] = 2; rowNumbers[19] = 1;
        rowNumbers[20] = 1; rowNumbers[21] = 3; rowNumbers[22] = 1; rowNumbers[23] = 3; rowNumbers[24] = 1;
        rowNumbers[25] = 3;

        rowNumbers[32] = 2; rowNumbers[33] = 3; rowNumbers[34] = 3; rowNumbers[35] = 2; rowNumbers[36] = 1;
        rowNumbers[37] = 2; rowNumbers[38] = 2; rowNumbers[39] = 2; rowNumbers[40] = 1; rowNumbers[41] = 2;
        rowNumbers[42] = 2; rowNumbers[43] = 2; rowNumbers[44] = 3; rowNumbers[45] = 3; rowNumbers[46] = 1;
        rowNumbers[47] = 1; rowNumbers[48] = 1; rowNumbers[49] = 1; rowNumbers[50] = 2; rowNumbers[51] = 1;
        rowNumbers[52] = 1; rowNumbers[53] = 3; rowNumbers[54] = 1; rowNumbers[55] = 3; rowNumbers[56] = 1;
        rowNumbers[57] = 3;
        ArrayList<String> res = new ArrayList<>();
        for (int i = 0; i < words.length; i++) {
            boolean isInOneRow = true;
            for (int j = 1; j < words[i].length(); j++) {
                if (rowNumbers[words[i].charAt(j) - 'A'] != rowNumbers[words[i].charAt(j-1) - 'A']) {
                    isInOneRow = false;
                    break;
                }
            }
            if (isInOneRow) {
                res.add(words[i]);
            }
        }
        return res.toArray(new String[0]);
    }
}

100%

最优解

class Solution {
    public String[] findWords(String[] words) {
        int[] R = {2,3,3,2,1,2,2,2,1,2,2,2,3,3,1,1,1,1,2,1,1,3,1,3,1,3};
        List<String> res = new ArrayList<>();
        for (String w: words) {
            boolean able = true;
            int line, l;
            if (w.length() >= 1) {
                if (w.charAt(0) <= 'Z') {
                    l = 0;
                } else {
                    l = 1;
                }
                line = R[(int)(w.charAt(0) - 'A' - l * ('a' - 'A'))];
                for (int i = 1; i < w.length() && able; ++i) {
                    if (w.charAt(i) <= 'Z') {
                        l = 0;
                    } else {
                        l = 1;
                    }
                    if (line != R[(int)(w.charAt(i)- 'A' - l * ('a' - 'A'))]) {
                        able = false;
                    }
                }
            }
            if (able) {
                res.add(w);
            }
        }
        String[] ress = new String[res.size()];
        for (int i=0;i<res.size();++i) {
            ress[i]=res.get(i);
        }

        return ress;
    }
}

一开始只初始化26个字母。 设置一个参数l,如果第一个字符是大写字母,l = 0, 否则 l = 1. 最后再看第一个字母在第几行。接着遍历这个单词的所有字母,如果不在这一行,able = false.

我的代码初始化时太蠢,而且判断是否在一行时,可以优化一下。

P501. Find Mode in Binary Search Tree (Easy)

给一个有重复值的BST, 找出所有的众数(出现次数最多的数)。

我的思路

因为是BST,所以重复的数一定是连着的。只要用递归返回它的长度即可。

写代码时发现刚才思路不清。每个节点的众数和它的子节点的众数是什么关系呢?我必须知道子节点每个数出现了多少次,然后再根据当前节点的值,看众数是否发生了改变。所以辅助方法应该返回一个HashMap, 记录下所有出现过的数的次数。

我的代码

public class E_501_FindModeInBST {

    private List<Integer> list = new ArrayList<>();

    public int[] findMode(TreeNode root) {
        HashMap<Integer, Integer> map = getMap(root);
        int max = Integer.MIN_VALUE;
        ArrayList<Integer> modes = new ArrayList<>();
        for (Integer value : map.values()) {
            if (value > max) {
                max = value;
            }
        }
        for (Integer integer : map.keySet()) {
            if (map.get(integer) == max) {
                modes.add(integer);
            }
        }
        int[] res = new int[modes.size()];
        for (int i = 0; i < modes.size(); i++) {
            res[i] = modes.get(i);
        }
        return res;
    }

    private HashMap<Integer, Integer> getMap(TreeNode root) {
        HashMap<Integer, Integer> map = new HashMap<>();
        if (root == null) {
            return map;
        }
        HashMap<Integer, Integer> leftMap = getMap(root.left);
        HashMap<Integer, Integer> rightMap = getMap(root.right);
        map.putAll(leftMap);
        rightMap.forEach((k,v) -> map.merge(k,v,Integer::sum));
        int val = root.val;
        if (map.containsKey(val)) {
            map.put(val, map.get(val) + 1);
        } else {
            map.put(val, 1);
        }
        return map;
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(4);
        TreeNode left = root.left = new TreeNode(3);
        TreeNode right = root.right = new TreeNode(6);
        left.left = new TreeNode(2);
        left.right = new TreeNode(4);
        left = right.left = new TreeNode(6);
        right = right.right = new TreeNode(7);
        left.left = new TreeNode(4);
        right.left = new TreeNode(4);
        right.right = new TreeNode(6);

        new E_501_FindModeInBST().findMode(root);
    }
}

5%

最优解

class Solution {
    private List<Integer> temp = new ArrayList();
    private int count = 0;
    private TreeNode prev = null;
    private int prevC = 0;
    public int[] findMode(TreeNode root) {
        if (root == null) {
            return new int[]{};
        }
        helper(root);
        int[] res = new int[temp.size()];
        for (int i = 0; i < res.length; i++) {
            res[i] = temp.get(i);
        }
        return res;
    }

    private void helper(TreeNode node) {
        if (node == null) {
            return;
        }
        helper(node.left);
        if (prev != null && prev.val == node.val) {
            prevC ++;
        }else{
            prevC = 1;
        }
        if (prevC > count) {
            count = prevC;
            temp = new ArrayList();
        }
        if (prevC == count) {
            temp.add(node.val);
        }
        prev = node;
        helper(node.right);
    }
}

因为是BST,所以即使有重复的值,通过中序遍历也一定能维持从小到大的顺序。

那么只需要记录下来前一个数,以及前面的最大次数,按要求更新结果集即可。

自己重写的代码

public class E_501_FindModeInBST {

    private List<Integer> res = new ArrayList<>();
    private int count = 0;
    private int max = 0;
    private Integer prev = null;

    public int[] findMode(TreeNode root) {
        dfs(root);
        int[] array = new int[res.size()];
        for (int i = 0; i < array.length; i++) {
            array[i] = res.get(i);
        }
        return array;
    }

    private void dfs(TreeNode node) {
        if (node == null) {
            return;
        }

        dfs(node.left);

        if (prev == null) {
            prev = node.val;
            count = 1;
        } else if (prev == node.val){
            count++;
        } else {
            count = 1;
            prev = node.val;
        }

        if (count > max) {
            max = count;
            res.clear();
            res.add(node.val);
        } else if (count == max) {
            res.add(node.val);
        }
        dfs(node.right);
    }
}

tags: LeetCode