Leetcode 262: Trips and Users

262. Trips and Users

  • Total Accepted: 6774
  • Total Submissions: 43127
  • Difficulty: Hard
  • Contributors: Admin

The Trips table holds all taxi trips. Each trip has a unique Id, while Client_Id and Driver_Id are both foreign keys to the Users_Id at the Users table. Status is an ENUM type of (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’).

+----+-----------+-----------+---------+--------------------+----------+
| Id | Client_Id | Driver_Id | City_Id |        Status      |Request_at|
+----+-----------+-----------+---------+--------------------+----------+
| 1  |     1     |    10     |    1    |     completed      |2013-10-01|
| 2  |     2     |    11     |    1    | cancelled_by_driver|2013-10-01|
| 3  |     3     |    12     |    6    |     completed      |2013-10-01|
| 4  |     4     |    13     |    6    | cancelled_by_client|2013-10-01|
| 5  |     1     |    10     |    1    |     completed      |2013-10-02|
| 6  |     2     |    11     |    6    |     completed      |2013-10-02|
| 7  |     3     |    12     |    6    |     completed      |2013-10-02|
| 8  |     2     |    12     |    12   |     completed      |2013-10-03|
| 9  |     3     |    10     |    12   |     completed      |2013-10-03| 
| 10 |     4     |    13     |    12   | cancelled_by_driver|2013-10-03|
+----+-----------+-----------+---------+--------------------+----------+

The Users table holds all users. Each user has an unique Users_Id, and Role is an ENUM type of (‘client’, ‘driver’, ‘partner’).

+----------+--------+--------+
| Users_Id | Banned |  Role  |
+----------+--------+--------+
|    1     |   No   | client |
|    2     |   Yes  | client |
|    3     |   No   | client |
|    4     |   No   | client |
|    10    |   No   | driver |
|    11    |   No   | driver |
|    12    |   No   | driver |
|    13    |   No   | driver |
+----------+--------+--------+

Write a SQL query to find the cancellation rate of requests made by unbanned clients between Oct 1, 2013 and Oct 3, 2013. For the above tables, your SQL query should return the following rows with the cancellation rate being rounded to two decimal places.

+------------+-------------------+
|     Day    | Cancellation Rate |
+------------+-------------------+
| 2013-10-01 |       0.33        |
| 2013-10-02 |       0.00        |
| 2013-10-03 |       0.50        |
+------------+-------------------+

 

Code

# Write your MySQL query statement below
select 
    Request_at as Day,
    round(count(IF(Status != 'completed', 1, NULL) ) / count(*), 2) as 'Cancellation Rate'
from Trips
join Users
on Users.Users_id = Trips.Client_Id
where 
    Banned = 'No' 
    and Request_at between '2013-10-01' and '2013-10-03'
group by Request_at

 

Idea

In order to calculate cancellation rate per day, you need to do group by Request_at. To count cancellation, we need to have an IF clause for counting. 

 

Reference: https://discuss.leetcode.com/topic/42188/solution-without-join/3

Leetsql 185: Department Top Three Salaries

185. Department Top Three Salaries

  • Total Accepted: 8926
  • Total Submissions: 57724
  • Difficulty: Hard
  • Contributors: Admin

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

+----+-------+--------+--------------+
| Id | Name  | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1  | Joe   | 70000  | 1            |
| 2  | Henry | 80000  | 2            |
| 3  | Sam   | 60000  | 2            |
| 4  | Max   | 90000  | 1            |
| 5  | Janet | 69000  | 1            |
| 6  | Randy | 85000  | 1            |
+----+-------+--------+--------------+

The Department table holds all departments of the company.

+----+----------+
| Id | Name     |
+----+----------+
| 1  | IT       |
| 2  | Sales    |
+----+----------+

Write a SQL query to find employees who earn the top three salaries in each of the department. For the above tables, your SQL query should return the following rows.

+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT         | Max      | 90000  |
| IT         | Randy    | 85000  |
| IT         | Joe      | 70000  |
| Sales      | Henry    | 80000  |
| Sales      | Sam      | 60000  |
+------------+----------+--------+

 

Code

# Write your MySQL query statement below
select d1.Name as Department, e1.Name as Employee, e1.Salary as Salary 
from Employee e1
join Department d1
on d1.Id = e1.DepartmentId
where 3 > (select count(distinct e2.Salary) 
           from Employee e2
           where e2.DepartmentId = e1.DepartmentId
           and e2.Salary > e1.Salary)

 

Idea

line 2~5 is just joining two tables, Employee and Department. line 6-9 makes sure the selection includes employees who earns top three.

 

Reference: https://discuss.leetcode.com/topic/8562/accepted-solution-without-group-by-or-order-by

LeetSql 177: Nth Highest Salary

177. Nth Highest Salary

  • Total Accepted: 12870
  • Total Submissions: 80808
  • Difficulty: Medium
  • Contributors: Admin

Write a SQL query to get the nth highest salary from the Employee table.

+----+--------+
| Id | Salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+

For example, given the above Employee table, the nth highest salary where n = 2 is 200. If there is no nth highest salary, then the query should return null.

 

Code

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  declare M INT;
  set M=N-1;
  RETURN (
      # Write your MySQL query statement below.
      select distinct Salary from Employee order by Salary desc limit M, 1
  );
END

 

Idea

limit M, 1 means return one element since M element.

Leetcode 40: Combination Sum II

40. Combination Sum II

  • Total Accepted: 89506
  • Total Submissions: 294097
  • Difficulty: Medium
  • Contributors: Admin

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:

[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

 

Code

class Solution(object):
    def combinationSum2(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        # no duplication in result. so sort candidates first.
        candidates = sorted(candidates)
    
        path, res = [], []
        self.dfs(0, candidates, path, res, target)
        return res
    
    def dfs(self, start_idx, candidates, path, res, target):
        # original target and all candidates are positive
        if target < 0:
            return
        elif target == 0:
            res.append(list(path))
            return
        
        for i in xrange(start_idx, len(candidates)):
            # remove duplication
            if i > start_idx and candidates[i] == candidates[i-1]:
                continue
            path.append(candidates[i])
            self.dfs(i+1, candidates, path, res, target-candidates[i])
            path.pop()
        

 

Idea

Essentially it is a DFS. In order to avoid duplicate combinations, we sort the candidates first (line 9) and also apply some mechanism at line 25. Then, we try adding `candidates[i]` to path, modifying target to `target-candidates[i]` and recurring on `dfs` method. 

Reference: https://discuss.leetcode.com/topic/19845/java-solution-using-dfs-easy-understand

Leetcode 341: Flatten Nested List Iterator

341. Flatten Nested List Iterator

  • Total Accepted: 20339
  • Total Submissions: 55207
  • Difficulty: Medium
  • Contributors: Admin

Given a nested list of integers, implement an iterator to flatten it.

Each element is either an integer, or a list — whose elements may also be integers or other lists.

Example 1:
Given the list [[1,1],2,[1,1]],

By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,1,2,1,1].

Example 2:
Given the list [1,[4,[6]]],

By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,4,6].

 

Code

# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger(object):
#    def isInteger(self):
#        """
#        @return True if this NestedInteger holds a single integer, rather than a nested list.
#        :rtype bool
#        """
#
#    def getInteger(self):
#        """
#        @return the single integer that this NestedInteger holds, if it holds a single integer
#        Return None if this NestedInteger holds a nested list
#        :rtype int
#        """
#
#    def getList(self):
#        """
#        @return the nested list that this NestedInteger holds, if it holds a nested list
#        Return None if this NestedInteger holds a single integer
#        :rtype List[NestedInteger]
#        """

class NestedIterator(object):

    def __init__(self, nestedList):
        """
        Initialize your data structure here.
        :type nestedList: List[NestedInteger]
        """
        # initialize a pair. 1st: the next element to explore, 
        # 2nd: the next index of that element to explore, if that element is a list-like NestedInteger
        self.stack = [[nestedList, 0]]
        
    def next(self):
        """
        :rtype: int
        """
        # hasNext() always makes sure the latest element on self.stack
        # is a list containing a non-list NestedInteger
        if self.hasNext():
            l, idx = self.stack.pop()
            return l.getInteger()

    def hasNext(self):
        """
        # hasNext() always makes sure the latest element on self.stack
        # is a list containing a non-list NestedInteger
        
        :rtype: bool
        """
        while self.stack:
            l, idx = self.stack[-1]
            if type(l) is NestedInteger and l.isInteger():
                return True
            else:
                if type(l) is NestedInteger and idx < len(l.getList()): 
                    self.stack[-1][1] += 1
                    self.stack.append([l.getList()[idx], 0])
                # the first added element in self.__init__ is a pure list    
                elif type(l) is list and idx < len(l):
                    self.stack[-1][1] += 1
                    self.stack.append([l[idx], 0])
                else:
                    # pop the element if the idx, the next position to explore, has already
                    # exceeded the length of the element
                    self.stack.pop()
        return False
        

# Your NestedIterator object will be instantiated and called as such:
# i, v = NestedIterator(nestedList), []
# while i.hasNext(): v.append(i.next())

 

Idea

Use a stack to maintain the elements to iterate. The next element to be iterated will be on the top of the stack. The stack is initialized as [nestedList, 0] in self.__init__(), as we are going to explore the first element in nestedList in the future.

In self.next(), we always first call self.hasNext(). The goal of self.hasNext() is to put the next integer on the top of the stack and also a boolean indicating whether there indeed exists the next integer to iterate.

In self.hasNext(), we peek the top element in the stack (line 55). If it is already an integer, return True and we don’t need to arrange the stack further. If it is a list of integers, we need to start exploring that list and put the next integer on the stack. Before that, we need to increase the top element’s index by one (line 60 and 64). This means that the next time when we visit this list, we should start exploring from the updated index.

The advantage of this algorithm is that it does not need to load all integers of the whole list into the stack at one time. Its space complexity is O(K), where K is the depth of the deepest nested list.

Reference: https://discuss.leetcode.com/topic/41870/real-iterator-in-python-java-c

Leetcode 27: Remove Element

27. Remove Element 

  • Total Accepted: 154492
  • Total Submissions: 426032
  • Difficulty: Easy
  • Contributors: Admin

Given an array and a value, remove all instances of that value in place and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

The order of elements can be changed. It doesn’t matter what you leave beyond the new length.

Example:
Given input array nums = [3,2,2,3], val = 3

Your function should return length = 2, with the first two elements of nums being 2.

Hint:

  1. Try two pointers.
  2. Did you use the property of “the order of elements can be changed”?
  3. What happens when the elements to remove are rare?

 

Code

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        left, right = 0, len(nums)-1
        while left <= right:
            if nums[left] == val:
                nums[left], nums[right] = nums[right], nums[left]
                right -= 1
            else:
                left += 1
            
        return right + 1

 

Idea

Everything on the right of right are elements equal to val.

Leetcode 29: Divide Two Integers

29. Divide Two Integers 

  • Total Accepted: 82624
  • Total Submissions: 519755
  • Difficulty: Medium
  • Contributors: Admin

Divide two integers without using multiplication, division and mod operator.

If it is overflow, return MAX_INT.

 

 

Code (Naive)

import sys


class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        if not divisor: return sys.maxint
        sign = -1 if (dividend > 0) ^ (divisor > 0) else 1
        dividend, divisor = abs(dividend), abs(divisor)

        res = 0
        while dividend - divisor >= 0:
            dividend -= divisor
            res += 1

        return res * sign

This is  a naive solution, where you count how many times dividend is to divisor by subtracting divisor from dividend until dividend < divisor. This solution causes Time Limit Error when dividend is large and divisor is small.

 

Code

import sys

class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        if not divisor: 
            return sys.maxint
        
        # In python there is no overflow issue.
        # This condition is here for a specific test case.
        if (dividend == -2**31 and divisor == -1):
            return 2**31-1
        
        sign = -1 if (dividend > 0) ^ (divisor > 0) else 1
        dividend, divisor = abs(dividend), abs(divisor)
    
        res = 0
        while dividend >= divisor:
            tmp_divisor = divisor
            tmp_multiple = 1
            while dividend >= (tmp_divisor << 1):
                tmp_divisor <<= 1
                tmp_multiple <<= 1
                
            dividend -= tmp_divisor
            res += tmp_multiple
        
        return res * sign

 

Idea

This is a quicker way to do the division. You approach to the quotient by doubling divisor until dividend < (tmp_divisor << 1). (line 22-27)

Reference: https://discuss.leetcode.com/topic/15568/detailed-explained-8ms-c-solution/2

 

Another idea is to use some mathematical properties to the quotient. If integer size is fixed at 32bit, then the algorithm takes constant time: https://discuss.leetcode.com/topic/17600/32-times-bit-shift-operation-in-c-with-o-1-solution

 

Leetcode 21: Merge Two Sorted Lists

21. Merge Two Sorted Lists

  • Total Accepted: 167826
  • Total Submissions: 448665
  • Difficulty: Easy
  • Contributors: Admin

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

Code

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        headbak = head = ListNode(0)
        while l1 and l2:
            if l1.val < l2.val:
                head.next = l1
                l1 = l1.next
            else:
                head.next = l2
                l2 = l2.next
                
            head = head.next
        
        while l1:
            head.next = l1
            l1 = l1.next
            head = head.next
        
        while l2:
            head.next = l2
            l2 = l2.next
            head = head.next
        
        return headbak.next

Idea

When two lists’ heads are not None, splice the smaller node into the new list and move the list’s head to the next of the smaller pointer. Then, when only one list’s head is not None, concatenate all of its remaining nodes.

See a harder version: Merge k sorted list: https//nb4799.neu.edu/wordpress/?p=926

Leetcode 14: Longest Common Prefix

14. Longest Common Prefix

  • Total Accepted: 131998
  • Total Submissions: 438812
  • Difficulty: Easy
  • Contributors: Admin

Write a function to find the longest common prefix string amongst an array of strings.

 

Code

class Solution(object):
    def longestCommonPrefix(self, strs):
        """
        :type strs: List[str]
        :rtype: str
        """
        if not strs:
            return ""
        
        prefix = ""
        for k in xrange(len(strs[0])):
            for i in xrange(1, len(strs)):
                if k < len(strs[i]) and strs[i][k] == strs[0][k]:
                    continue
                return prefix
            prefix += strs[0][k]
        
        return prefix

 

Idea

Suppose there are N strings and average K length for each string. Then this algorithm takes O(NK) time, which I believe is the fastest solution so far. Note that we start prefix from an empty string. In this way, we only need to test whether to add one character to prefix each time. 

 

Reference: https://discuss.leetcode.com/topic/20991/accepted-c-6-lines-4ms/6