Leetsql 182: Duplicate Emails

182. Duplicate Emails 

  • Total Accepted: 27110
  • Total Submissions: 73222
  • Difficulty: Easy
  • Contributors: Admin

Write a SQL query to find all duplicate emails in a table named Person.

+----+---------+
| Id | Email   |
+----+---------+
| 1  | a@b.com |
| 2  | c@d.com |
| 3  | a@b.com |
+----+---------+

For example, your query should return the following for the above table:

+---------+
| Email   |
+---------+
| a@b.com |
+---------+

Note: All emails are in lowercase.

 

Idea

# Write your MySQL query statement below
select distinct p1.Email as Email from Person p1, Person p2
where p1.Email = p2.Email and p1.Id != p2.Id

 

There are many other ways: https://discuss.leetcode.com/topic/7485/i-have-this-simple-approach-anybody-has-some-other-way

Leetcode 221: Maximal Square

  • Total Accepted: 44584
  • Total Submissions: 169331
  • Difficulty: Medium
  • Contributors: Admin

Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s and return its area.

For example, given the following matrix:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

Return 4.

 

Code

class Solution(object):
    def maximalSquare(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        if not matrix:
            return 0
        
        # convert to integer matrix
        for i in xrange(len(matrix)):
            for j in xrange(len(matrix[0])):
                matrix[i][j] = int(matrix[i][j])
            
        max_size = max(matrix[0])
        # DP storage initialized with the first row of matrix
        vec = list(matrix[0])
        
        for row in xrange(1, len(matrix)):
            topleft = vec[0]
            vec[0] = matrix[row][0]
            
            for col in xrange(1, len(matrix[0])):
                if matrix[row][col] == 0:
                    new = 0
                else:
                    new = min(topleft, vec[col-1], vec[col]) + 1
                topleft = vec[col]
                vec[col] = new
            
            max_size = max(max_size, max(vec))
                
        return max_size * max_size
        
        
        

 

Idea

Think about it as a 2D DP problem. Suppose a list vec has size num_row * num_col. vec[i][j] is the size of the maximum square that can be achieved at matrix[i][j]. The core logic is that vec[i][j] = min(vec[i][j-1], vec[i-1][j],vec[i-1][j-1]). 

And we know that 2D DP problem can often be reduced to 1D. That’s how I implement currently.

Reference:

https://discuss.leetcode.com/topic/15328/easy-dp-solution-in-c-with-detailed-explanations-8ms-o-n-2-time-and-o-n-space

 

Leetcode 211: Add and Search Word – Data structure design

211. Add and Search Word – Data structure design 

  • Total Accepted: 37880
  • Total Submissions: 188966
  • Difficulty: Medium
  • Contributors: Admin

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 letters a-z or .. A . means it can represent any one letter.

For example:

addWord("bad")
addWord("dad")
addWord("mad")
search("pad") -> false
search("bad") -> true
search(".ad") -> true
search("b..") -> true

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

click to show hint.

You should be familiar with how a Trie works. If not, please work on this problem: Implement Trie (Prefix Tree) first.

 

Code

class TrieNode():
    def __init__(self):
        self.nodes = {}
        self.isword = False
    
class WordDictionary(object):
    def __init__(self):
        """
        initialize your data structure here.
        """
        self.root = TrieNode()

    def addWord(self, word):
        """
        Adds a word into the data structure.
        :type word: str
        :rtype: void
        """
        root = self.root
        for i, ch in enumerate(word):
            if not root.nodes.get(ch, None):
                root.nodes[ch] = TrieNode()
            root = root.nodes[ch]
            if i == len(word) - 1:
                root.isword = True

    def search(self, word):
        """
        Returns if the word is in the data structure. A word could
        contain the dot character '.' to represent any one letter.
        :type word: str
        :rtype: bool
        """
        assert len(word) > 0
        return self.search_helper(word, 0, self.root)
        
    def search_helper(self, word, idx, root):
        ch = word[idx]
        if ch == '.':
            if idx == len(word) - 1:
                 return any(map(lambda x: x.isword, root.nodes.values()))
            else:
                 return any(map(lambda x: self.search_helper(word, idx+1, x), root.nodes.values()))
        else:
            if root.nodes.get(ch, None) is None:
                return False
            else:
                if idx == len(word) - 1:
                    return root.nodes[ch].isword
                else:
                    return self.search_helper(word, idx+1, root.nodes[ch])
        
        

# Your WordDictionary object will be instantiated and called as such:
# wordDictionary = WordDictionary()
# wordDictionary.addWord("word")
# wordDictionary.search("pattern")

 

Idea

Use Trie structure to store words and make search. Assume we have O(N) words and each word has O(K) length. Then each add takes O(K) time and O(K) space. Each search takes O(K) time . See another post: https//nb4799.neu.edu/wordpress/?p=1162

Leetcode 252: Meeting Rooms

https://leetcode.com/problems/meeting-rooms/

252. Meeting Rooms

  • Total Accepted: 19160
  • Total Submissions: 43021
  • Difficulty: Easy
  • Contributors: Admin

Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), determine if a person could attend all meetings.

For example,
Given [[0, 30],[5, 10],[15, 20]],
return false.

 
 

Code

# Definition for an interval.
# class Interval(object):
#     def __init__(self, s=0, e=0):
#         self.start = s
#         self.end = e

class Solution(object):
    def canAttendMeetings(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: bool
        """
        if not intervals or len(intervals) == 1:
            return True
        
        intervals = sorted(intervals, key=lambda x: x.start)
        
        for i in xrange(1, len(intervals)):
            if intervals[i].start < intervals[i-1].end:
                return False
        
        return True

 

Idea

You have to sort first which takes O(nlogn) time.

You can also look at the similar problem: https//nb4799.neu.edu/wordpress/?p=2205 

Leetcode 181: Employees Earning More Than Their Managers

https://leetcode.com/problems/employees-earning-more-than-their-managers/

181. Employees Earning More Than Their Managers

  • Total Accepted: 27138
  • Total Submissions: 76486
  • Difficulty: Easy
  • Contributors: Admin

The Employee table holds all employees including their managers. Every employee has an Id, and there is also a column for the manager Id.

+----+-------+--------+-----------+
| Id | Name  | Salary | ManagerId |
+----+-------+--------+-----------+
| 1  | Joe   | 70000  | 3         |
| 2  | Henry | 80000  | 4         |
| 3  | Sam   | 60000  | NULL      |
| 4  | Max   | 90000  | NULL      |
+----+-------+--------+-----------+

Given the Employee table, write a SQL query that finds out employees who earn more than their managers. For the above table, Joe is the only employee who earns more than his manager.

+----------+
| Employee |
+----------+
| Joe      |
+----------+

 

Code

# Write your MySQL query statement below
select Name as "Employee" 
from Employee e1
where e1.Salary > (select e2.Salary from Employee e2 where e2.Id = e1.ManagerId)

 

Idea

Nothing too much.

Leetcode 180: Consecutive Numbers

180. Consecutive Numbers

  • Total Accepted: 12576
  • Total Submissions: 52571
  • Difficulty: Medium
  • Contributors: Admin

Write a SQL query to find all numbers that appear at least three times consecutively.

+----+-----+
| Id | Num |
+----+-----+
| 1  |  1  |
| 2  |  1  |
| 3  |  1  |
| 4  |  2  |
| 5  |  1  |
| 6  |  2  |
| 7  |  2  |
+----+-----+

For example, given the above Logs table, 1 is the only number that appears consecutively for at least three times.

 

Code

# Write your MySQL query statement below
select distinct l1.Num as ConsecutiveNums
from Logs l1, Logs l2, Logs l3
where l1.Id = l2.Id -1 and l1.Id = l3.Id-2 and l1.Num = l2.Num and l1.Num = l3.Num

 

Idea

For this kind of problems, you need to have multiple instances of the same table (Logs l1, Logs l2, Logs l3).

 

Leetcode 178: Rank Score

  • Total Accepted: 13824
  • Total Submissions: 58154
  • Difficulty: Medium
  • Contributors: Admin

Write a SQL query to rank scores. If there is a tie between two scores, both should have the same ranking. Note that after a tie, the next ranking number should be the next consecutive integer value. In other words, there should be no “holes” between ranks.

+----+-------+
| Id | Score |
+----+-------+
| 1  | 3.50  |
| 2  | 3.65  |
| 3  | 4.00  |
| 4  | 3.85  |
| 5  | 4.00  |
| 6  | 3.65  |
+----+-------+

For example, given the above Scores table, your query should generate the following report (order by highest score):

+-------+------+
| Score | Rank |
+-------+------+
| 4.00  | 1    |
| 4.00  | 1    |
| 3.85  | 2    |
| 3.65  | 3    |
| 3.65  | 3    |
| 3.50  | 4    |
+-------+------+

 

Code

# Write your MySQL query statement below
select Score,
(select count(distinct s2.Score) from Scores s2 where s2.score >= s1.score) as Rank
from  Scores s1
order by Score desc

 

Idea

Select count(*)… result can be returned as a column.

 

Leetcode 3466: Moving Average from Data Stream

346. Moving Average from Data Stream

  • Total Accepted: 11701
  • Total Submissions: 20717
  • Difficulty: Easy
  • Contributors: Admin

Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window.

For example,

MovingAverage m = new MovingAverage(3);
m.next(1) = 1
m.next(10) = (1 + 10) / 2
m.next(3) = (1 + 10 + 3) / 3
m.next(5) = (10 + 3 + 5) / 3

 

Code

class MovingAverage(object):

    def __init__(self, size):
        """
        Initialize your data structure here.
        :type size: int
        """
        self.size = size
        self.vals = [0]* size
        self.cnt = 0
        self.sum = 0

    def next(self, val):
        """
        :type val: int
        :rtype: float
        """
        self.cnt += 1
        idx = (self.cnt - 1) % self.size 

        # replace old value
        self.sum -= self.vals[idx]
        self.sum += val
        self.vals[idx] = val

        return float(self.sum) / self.cnt if self.cnt < self.size \
            else float(self.sum) / self.size

# Your MovingAverage object will be instantiated and called as such:
# obj = MovingAverage(size)
# param_1 = obj.next(val)

 

Idea

A cyclic list

 

You can also use deque however when you calculate average it takes O(K) time where K is the window size.: https://discuss.leetcode.com/topic/44116/4-line-python-solution-using-deque

Leetcode 163: Missing Ranges

163. Missing Ranges

  • Total Accepted: 19465
  • Total Submissions: 66232
  • Difficulty: Medium
  • Contributors: Admin

Given a sorted integer array where the range of elements are in the inclusive range [lower, upper], return its missing ranges.

For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"].

 

Code

class Solution(object):
    def findMissingRanges(self, nums, lower, upper):
        """
        :type nums: List[int]
        :type lower: int
        :type upper: int
        :rtype: List[str]
        """
        if nums is None:
            nums = []
        
        res = []
        nums = [lower-1] + nums + [upper+1]

        for i in xrange(1, len(nums)):
            prev, cur = nums[i-1], nums[i]
            if cur - prev == 2:
                res.append(str(cur-1))
            elif cur - prev > 2:
                res.append(str(prev+1) + '->' + str(cur-1))

        return res

 

Idea

To make the code consistent in different cases, I add lower-1 in front of nums and append upper+1 in the end of nums. Then if the current element is exactlye greater than the previous element by 2, then we miss a single number; else, if the current element is greater than the previous element more than 2, then we miss a range; if the current element is just 1 greater than the previous element, we do not do anything.

 

Also see a similar question: https//nb4799.neu.edu/wordpress/?p=944

Leetcode 388: Longest Absolute File Path

388. Longest Absolute File Path

  • Total Accepted: 11837
  • Total Submissions: 35565
  • Difficulty: Medium
  • Contributors: Admin

Suppose we abstract our file system by a string in the following manner:

The string "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext" represents:

dir
    subdir1
    subdir2
        file.ext

The directory dir contains an empty sub-directory subdir1 and a sub-directory subdir2 containing a file file.ext.

The string "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext" represents:

dir
    subdir1
        file1.ext
        subsubdir1
    subdir2
        subsubdir2
            file2.ext

The directory dir contains two sub-directories subdir1 and subdir2. subdir1 contains a file file1.ext and an empty second-level sub-directory subsubdir1. subdir2contains a second-level sub-directory subsubdir2 containing a file file2.ext.

We are interested in finding the longest (number of characters) absolute path to a file within our file system. For example, in the second example above, the longest absolute path is"dir/subdir2/subsubdir2/file2.ext", and its length is 32 (not including the double quotes).

Given a string representing the file system in the above format, return the length of the longest absolute path to file in the abstracted file system. If there is no file in the system, return0.

Note:

  • The name of a file contains at least a . and an extension.
  • The name of a directory or sub-directory will not contain a ..

Time complexity required: O(n) where n is the size of the input string.

Notice that a/aa/aaa/file1.txt is not the longest file path, if there is another path aaaaaaaaaaaaaaaaaaaaa/sth.png.

 

Code

class Solution(object):
    def lengthLongestPath(self, input):
        """
        :type input: str
        :rtype: int
        """
        if not input:
            return 0
        
        longest = 0
        prev_tab_cnt = 0
        # store tuples (name, level)
        stk = []

        s = input.split('\n')
        
        for ss in s:
            ss_tab_cnt = 0
            while ss.startswith('\t'):
                ss_tab_cnt += 1
                # \t only takes one character
                ss = ss[1:]
            
            while stk and stk[-1][1] >= ss_tab_cnt:
                stk.pop()
            stk.append((ss, ss_tab_cnt))
            if self.isfile(ss):
                longest = max(longest, len('/'.join(map(lambda x: x[0], stk))))

        return longest

    def isfile(self, s):
        if s.startswith('.') or len(s.split('.')) >= 2:
            return True
        else:
            return False

 

Idea

Maintain a stack which stores the names of file/directory as well as their levels. Whenever you see it is a file name, concatenate all names in the stack. Whenever you see the current level is less than the stack top’s level, that means the previous trace has ended and the current file/directory starts from some upper level. So you need to pop stack (line 24~25).

 

You can change stack to dictionary. Reference: https://discuss.leetcode.com/topic/55097/simple-python-solution