面试笔试杂项积累-leetcode 211-215

来源:互联网 发布:js 自定义属性 data 编辑:程序博客网 时间:2024/06/05 23:06

211.211-Add and Search Word - Data structure design-Difficulty: Medium

Design a data structure that supports the following two operations:

void addWord(word)bool search(word)

search(word) can search a literal word or a regular expression string containing only lettersa-z or .. A . means it can represent any one letter.

For example:

addWord("bad")addWord("dad")addWord("mad")search("pad") -> falsesearch("bad") -> truesearch(".ad") -> truesearch("b..") -> true
Note:
You may assume that all words are consist of lowercase letters a-z.

思路

思路和208题字典树一样的,就多了.模糊查询

循环查询会超时,使用递归解决

public class WordDictionary {    class TrieNode    {        public TrieNode[] child;        public char val;        public bool isOnly = false;        // Initialize your data structure here.        public TrieNode()        {            this.child = new TrieNode[26];        }    }     private TrieNode root;        public WordDictionary()        {            root = new TrieNode();        }        // Inserts a word into the trie.        public void AddWord(string word)        {            TrieNode temp = root;            for (int j = 0; j < word.Length; j++)            //      for (int i = 0; i < 26; i++)            {                if (temp.child[word[j] - 97] == null)                {                    temp.child[word[j] - 97] = new TrieNode();                    temp.child[word[j] - 97].val = word[j];                }                temp = temp.child[word[j] - 97];            }            temp.isOnly = true;        }        // Returns if the word is in the trie.        public bool Search(string word)        {            return Searching(word, root);        }         bool Searching(string word, TrieNode node)        {        if (node == null)            return false;        if (word.Length == 0)            return node != null && node.isOnly;        if (word.Length > 0 && word[0] == '.')        {            foreach (TrieNode child in node.child)                if (Searching(word.Substring(1), child))                    return true;        }        else        {            TrieNode temp = node;            if (temp.child[word[0] - 97] == null)                return false;            temp = temp.child[word[0] - 97];            if (Searching(word.Substring(1), temp))                return true;        }        return false;        }}// Your WordDictionary object will be instantiated and called as such:// WordDictionary wordDictionary = new WordDictionary();// wordDictionary.AddWord("word");// wordDictionary.Search("pattern");

212.212-Word Search II-Difficulty: Hard

Given a 2D board and a list of words from the dictionary, find all words in the board.

Each word must 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 in a word.

For example,
Given words = ["oath","pea","eat","rain"] and board =

[  ['o','a','a','n'],  ['e','t','a','e'],  ['i','h','k','r'],  ['i','f','l','v']]
Return ["eat","oath"].

Note:
You may assume that all inputs are consist of lowercase letters a-z.

click to show hint.

You would need to optimize your backtracking to pass the larger test. Could you stop backtracking earlier?

If the current candidate does not exist in all words' prefix, you could stop backtracking immediately. What kind of data structure could answer such query efficiently? Does a hash table work? Why or why not? How about a Trie? If you would like to learn how to implement a basic trie, please work on this problem:Implement Trie (Prefix Tree) first.

方法一

思路

开始使用200题Number of Islands那样的做法来做,可以实现但是超时了,于是乎后来依旧用字典树,然后通过了

这里给出超时方法

 public IList<string> FindWords(char[,] board, string[] words)    {        IList<string> fin = new List<string>();        int row = board.GetLength(0);        int col = board.GetLength(1);        bool isBreak = false;        for (int i = 0; i < words.Length; i++)        {            for (int j = 0; j < row; j++)            {                for (int w = 0; w < col; w++)                {                    if (board[j, w] == words[i][0] && search(board, words[i], j, w))                    {                        fin.Add(words[i]);                        isBreak = true;                        break;                    }                }                if (isBreak)                {                    isBreak = false;                    break;                }            }        }        return fin;    }    bool search(char[,] board, string words, int m, int n)    {        if (words.Length == 0)            return true;        if (m > board.GetLength(0) - 1 || m < 0 || n > board.GetLength(1) - 1 || n < 0)            return false;        if (board[m, n] == words[0])        {            if (search(board, words.Substring(1), m + 1, n)) return true;            if (search(board, words.Substring(1), m - 1, n)) return true;            if (search(board, words.Substring(1), m, n + 1)) return true;            if (search(board, words.Substring(1), m, n - 1)) return true;        }        else            return false;        return false;    }

方法二

思路

字典树的方法在配合着上一种超时方法的思路

public class Solution {        class TrieNode    {        public TrieNode[] child;        public char val;        public bool isOnly = false;        // Initialize your data structure here.        public TrieNode()        {            this.child = new TrieNode[26];        }    }            private TrieNode root;        public Solution()        {            root = new TrieNode();        }      public void AddWord(string word)        {            TrieNode temp = root;            for (int j = 0; j < word.Length; j++)            //      for (int i = 0; i < 26; i++)            {                if (temp.child[word[j] - 97] == null)                {                    temp.child[word[j] - 97] = new TrieNode();                    temp.child[word[j] - 97].val = word[j];                }                temp = temp.child[word[j] - 97];            }            temp.isOnly = true;        }        public bool Search(string word)        {            TrieNode temp = root;            for (int j = 0; j < word.Length; j++)            {                if (temp.child[word[j] - 97] == null)                {                    return false;                }                temp = temp.child[word[j] - 97];            }            if (temp.isOnly)                return true;            return false;        }        public bool StartsWith(string word)        {            TrieNode temp = root;            for (int j = 0; j < word.Length; j++)            {                if (temp.child[word[j] - 97] == null)                {                    return false;                }                temp = temp.child[word[j] - 97];            }            return true;        }        IList<string> fin = new List<string>();        public IList<string> FindWords(char[,] board, string[] words)        {     for (int i = 0; i < words.Length; i++)                AddWord(words[i]);            int row = board.GetLength(0);            int col = board.GetLength(1);            bool[,] visited = new bool[row, col];            for (int j = 0; j < row; j++)            {                for (int w = 0; w < col; w++)                {                    if (StartsWith(board[j, w].ToString()))                        searching(board, visited, "", j, w);                }            }            return fin;        }        void searching(char[,] board, bool[,] visited, string words, int m, int n)        {             if (m > board.GetLength(0) - 1 || m < 0 || n > board.GetLength(1) - 1 || n < 0 || visited[m, n])            {           //     if (Search(words))         //           if (!fin.Contains(words)) fin.Add(words);                return;            }            if (Search(words + board[m, n]))            {                if (!fin.Contains(words + board[m, n]))                    fin.Add(words + board[m, n]);           //     return;            }            visited[m, n] = true;            if (StartsWith(words + board[m, n]))            {                searching(board, visited, words + board[m, n], m + 1, n);                searching(board, visited, words + board[m, n], m - 1, n);                searching(board, visited, words + board[m, n], m, n + 1);                searching(board, visited, words + board[m, n], m, n - 1);            }            visited[m, n] = false;        }}

213.213-Word Search II-Difficulty: Medium

After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place arearranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonightwithout alerting the police.

思路

和前面Word Search的区别就是小区连成环了,收尾相接

这里就计算两次,一次是头到尾前一个,一个是头后一个到尾。来避免头尾一同偷窃。最后取二者最大值即可

public class Solution {    public int Rob(int[] nums) {    if (nums == null || nums.Length == 0)            return 0;        int n = nums.Length;        if (n == 1)        {            return nums[0];        }        return Math.Max(Helper(nums, 0, n - 2), Helper(nums, 1, n - 1));    }    public int Helper(int[] nums,int start,int end)    { int curr, prev, prev2;            curr = prev = prev2 = 0;            for (int i = start; i <= end; i++) {                curr = Math.Max(prev2 + nums[i], prev);                prev2 = prev;                prev = curr;            }            return curr;    }}


215.215-Kth Largest Element in an Array-Difficulty: Medium

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.

方法一

思路

找到第k大的数

这里用两种方法可以解决,一种就是低级方法,排序后遍历得到,还有一种是快速排序,

这是低级方法

public class Solution {    public int FindKthLargest(int[] nums, int k) {        Array.Sort(nums);        return nums[nums.Length - k];    }}

方法二

思路

使用快排

参考:

https://leetcode.com/discuss/69427/concise-java-solution-based-on-quick-select

http://blog.csdn.net/v_JULY_v
http://blog.csdn.net/wolf96/article/details/50651594


Since we can sort the file in O(nlog n) time, one might expect to obtain a better time bound for selection. The algorithm we present to find the kth smallest element in a set S is almost identical to quicksort. In fact, the first three steps are the same. We will call this algorithm quickselect(叫做快速选择). Let |Si| denote the number of elements in Si(令|Si|为Si中元素的个数). The steps of quickselect are:

    1. If |S| = 1, then k = 1 and return the elements in S as the answer. If a cutoff for small files is being used and |S| <=CUTOFF, then sort S and return the kth smallest element.
    2. Pick a pivot element, v (- S.(选取一个枢纽元v属于S)
    3. Partition S - {v} into S1 and S2, as was done with quicksort.
(将集合S-{v}分割成S1和S2,就像我们在快速排序中所作的那样)

    4. If k <= |S1|, then the kth smallest element must be in S1. In this case, return quickselect (S1, k). If k = 1 + |S1|, then the pivot is the kth smallest element and we can return it as the answer. Otherwise, the kth smallest element lies in S2, and it is the (k - |S1| - 1)st smallest element in S2. We make a recursive call and return quickselect (S2, k - |S1| - 1).
(如果k<=|S1|,那么第k个最小元素必然在S1中。在这种情况下,返回quickselect(S1,k)。如果k=1+|S1|,那么枢纽元素就是第k个最小元素,即找到,直接返回它。否则,这第k个最小元素就在S2中,即S2中的第(k-|S1|-1)个最小元素,我们递归调用并返回quickselect(S2,k-|S1|-1))(下面几节的程序关于k的表述可能会有所出入,但无碍,抓住原理即ok)。

    In contrast to quicksort, quickselect makes only one recursive call instead of two. The worst case of quickselect is identical to that of quicksort and is O(n2). Intuitively, this is because quicksort's worst case is when one of S1 and S2 is empty; thus, quickselect(快速选择) is not really saving a recursive call. The average running time, however, is O(n)(不过,其平均运行时间为O(N)。看到了没,就是平均复杂度为O(N)这句话). The analysis is similar to quicksort's and is left as an exercise.

    The implementation of quickselect is even simpler than the abstract description might imply. The code to do this shown in Figure 7.16. When the algorithm terminates, the kth smallest element is in position k. This destroys the original ordering; if this is not desirable, then a copy must be made.



The basic idea is to use Quick Select algorithm to partition the array with pivot:

Put numbers < pivot to pivot's leftPut numbers > pivot to pivot's right

Then

if indexOfPivot == k, return A[k]else if indexOfPivot < k, keep checking left part to pivotelse if indexOfPivot > k, keep checking right part to pivot

Time complexity = O(n)

Discard half each time: n+(n/2)+(n/4)..1 = n + (n-1) = O(2n-1) = O(n), because n/2+n/4+n/8+..1=n-1.

Quick Select Solution Code:

public int findKthLargest(int[] nums, int k) {    if (nums == null || nums.length == 0) return Integer.MAX_VALUE;    return findKthLargest(nums, 0, nums.length - 1, nums.length - k);}    public int findKthLargest(int[] nums, int start, int end, int k) {// quick select: kth smallest    if (start > end) return Integer.MAX_VALUE;    int pivot = nums[end];// Take A[end] as the pivot,     int left = start;    for (int i = start; i < end; i++) {        if (nums[i] <= pivot) // Put numbers < pivot to pivot's left            swap(nums, left++, i);              }    swap(nums, left, end);// Finally, swap A[end] with A[left]    if (left == k)// Found kth smallest number        return nums[left];    else if (left < k)// Check right part        return findKthLargest(nums, left + 1, end, k);    else // Check left part        return findKthLargest(nums, start, left - 1, k);} void swap(int[] A, int i, int j) {    int tmp = A[i];    A[i] = A[j];    A[j] = tmp;             }











1 0
原创粉丝点击