LeetCode 211-220

2020-11-19  本文已影响0人  1nvad3r

211. 添加与搜索单词 - 数据结构设计

class WordDictionary {
    class TrieNode {
        TrieNode[] links;
        boolean end;

        public TrieNode() {
            this.links = new TrieNode[26];
        }
    }

    TrieNode root;

    public WordDictionary() {
        this.root = new TrieNode();
    }

    public void addWord(String word) {
        TrieNode cur = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            if (cur.links[c - 'a'] == null) {
                cur.links[c - 'a'] = new TrieNode();
            }
            cur = cur.links[c - 'a'];
        }
        cur.end = true;
    }

    private boolean helper(String word, TrieNode root) {
        TrieNode cur = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            if (c != '.') {
                if (cur.links[c - 'a'] != null) {
                    cur = cur.links[c - 'a'];
                } else {
                    return false;
                }
            } else {
                for (int j = 0; j < 26; j++) {
                    if (cur.links[j] != null && helper(word.substring(i + 1), cur.links[j])) {
                        return true;
                    }
                }
                return false;
            }
        }
        return cur.end;
    }

    public boolean search(String word) {
        return helper(word, root);
    }
}

212. 单词搜索 II

class Solution {
    int[] X = {0, 0, 1, -1}, Y = {1, -1, 0, 0};
    boolean[][] isVisit;

    private boolean helper(char[][] board, int i, int j, int num, String word) {
        if (num == word.length()) {
            return true;
        }
        if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || isVisit[i][j] == true) {
            return false;
        }
        if (board[i][j] == word.charAt(num)) {
            isVisit[i][j] = true;
            for (int k = 0; k < 4; k++) {
                int newI = i + X[k], newJ = j + Y[k];
                if (helper(board, newI, newJ, num + 1, word) == true) {
                    return true;
                }
            }
            isVisit[i][j] = false;
            return false;
        } else {
            return false;
        }
    }

    public List<String> findWords(char[][] board, String[] words) {
        isVisit = new boolean[board.length][board[0].length];
        Set<String> set = new HashSet<>();
        for (String word : words) {
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[0].length; j++) {
                    for (int k = 0; k < board.length; k++) {
                        Arrays.fill(isVisit[k], false);
                    }
                    if (helper(board, i, j, 0, word)) {
                        set.add(word);
                    }
                }
            }
        }
        return new ArrayList<>(set);
    }
}

213. 打家劫舍 II

偷第一间就不能偷最后一间,不偷第一间就可以偷最后一间。取两种情况的较大值。

class Solution {
    public int rob(int[] nums) {
        int[] dp = new int[nums.length];//偷第一间
        dp[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (i == nums.length - 1) {
                dp[i] = dp[i - 1];
                continue;
            }
            dp[i] = Math.max((i - 2 >= 0 ? dp[i - 2] : 0) + nums[i], dp[i - 1]);
        }
        int res = dp[nums.length - 1];
        Arrays.fill(dp, 0);//不偷第一间
        for (int i = 1; i < nums.length; i++) {
            dp[i] = Math.max((i - 2 >= 0 ? dp[i - 2] : 0) + nums[i], dp[i - 1]);
        }
        return Math.max(res, dp[nums.length - 1]);
    }
}

214. 最短回文串

暴力法:
不断从大到小枚举s的前缀,只要某个前缀是回文串,那么把后面的子串反转之后加到前面,便是最短的回文串。
时间复杂度On2,最后一个案例超时。

class Solution {
    private boolean isPar(String s) {
        if ("".equals(s)) {
            return true;
        }
        int i = 0, j = s.length() - 1;
        while (i < j) {
            if (s.charAt(i++) != s.charAt(j--)) {
                return false;
            }
        }
        return true;
    }

    public String shortestPalindrome(String s) {
        if ("".equals(s)) {
            return "";
        }
        StringBuilder res = new StringBuilder();
        for (int i = s.length() - 1; i >= 0; i--) {
            if (isPar(s.substring(0, i + 1))) {
                StringBuilder str = new StringBuilder(s.substring(i + 1));
                str.reverse();
                res.append(str).append(s);
                return res.toString();
            }
        }
        StringBuilder str = new StringBuilder(s.substring(1));
        str.reverse();
        res.append(str).append(s);
        return res.toString();
    }
}

字符串哈希:
如果测试数据比较刁钻,改一下base和mod或者在left==right的时候加一个双重验证,手动判断是不是回文串。

class Solution {
    public String shortestPalindrome(String s) {
        int len = s.length();
        long base = 131, mod = 1000000007;
        long left = 0, right = 0, mul = 1, best = -1;
        for (int i = 0; i < len; i++) {
            left = (left * base + s.charAt(i)) % mod;
            right = (right + mul * s.charAt(i)) % mod;
            if (left == right) {
                best = i;
            }
            mul = mul * base % mod;
        }
        String add = (best == len - 1 ? "" : s.substring((int) best + 1));
        StringBuilder res = new StringBuilder(add).reverse();
        res.append(s);
        return res.toString();
    }
}

215. 数组中的第K个最大元素

自己写的快排37ms。

class Solution {
    public int partition(int lo, int hi, int[] nums) {
        int temp = nums[lo];
        while (lo < hi) {
            while (lo < hi && nums[hi] > temp) {
                hi--;
            }
            nums[lo] = nums[hi];
            while (lo < hi && nums[lo] < temp) {
                lo++;
            }
            nums[hi] = nums[lo];
        }
        nums[lo] = temp;
        return lo;
    }

    public void quickSort(int lo, int hi, int[] nums) {
        if (lo < hi) {
            int pivot = partition(lo, hi, nums);
            quickSort(lo, pivot - 1, nums);
            quickSort(pivot + 1, hi, nums);
        }
    }

    public int findKthLargest(int[] nums, int k) {
        quickSort(0, nums.length - 1, nums);
        return nums[nums.length - k];
    }
}

库函数的快排2ms。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length - k];
    }
}

最大堆 2ms:

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int heapSize = nums.length;
        buildMaxHeap(nums, heapSize);
        for (int i = nums.length - 1; i >= nums.length - k + 1; --i) {
            swap(nums, 0, i);
            --heapSize;
            maxHeapify(nums, 0, heapSize);
        }
        return nums[0];
    }

    public void buildMaxHeap(int[] a, int heapSize) {
        for (int i = heapSize / 2; i >= 0; --i) {
            maxHeapify(a, i, heapSize);
        } 
    }

    public void maxHeapify(int[] a, int i, int heapSize) {
        int l = i * 2 + 1, r = i * 2 + 2, largest = i;
        if (l < heapSize && a[l] > a[largest]) {
            largest = l;
        } 
        if (r < heapSize && a[r] > a[largest]) {
            largest = r;
        }
        if (largest != i) {
            swap(a, i, largest);
            maxHeapify(a, largest, heapSize);
        }
    }

    public void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

216. 组合总和 III

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    public void dfs(int begin, int k, int n) {
        if (n < 0 || k < 0) {
            return;
        }
        if (k == 0 && n == 0) {
            res.add(new ArrayList<>(temp));
        }
        for (int i = begin; i <= 9; i++) {
            temp.add(i);
            dfs(i + 1, k - 1, n - i);
            temp.remove(temp.size() - 1);
        }
    }

    public List<List<Integer>> combinationSum3(int k, int n) {
        dfs(1, k, n);
        return res;
    }
}

217. 存在重复元素

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for (int i : nums) {
            if (!set.add(i)) {
                return true;
            }
        }
        return false;
    }
}

218. 天际线问题

线段树,面试应该不会考,先不做了。

219. 存在重复元素 II

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(nums[i])) {
                if (i - map.get(nums[i]) <= k) {
                    return true;
                } else {
                    map.put(nums[i], i);
                }
            } else {
                map.put(nums[i], i);
            }
        }
        return false;
    }
}
上一篇下一篇

猜你喜欢

热点阅读