题目序号 71、93、208、211、24、179、228

71. Simplify Path

Given an absolute path for a file (Unix-style), simplify it.

For example, path = “/home/”, => “/home” path = “/a/./b/../../c/”, => “/c” path = “/a/../../b/../c//.//”, => “/c” path = “/a//b////c/d//././/..”, => “/a/b/c”

In a UNIX-style file system, a period (‘.’) refers to the current directory, so it can be ignored in a simplified path. Additionally, a double period (“..”) moves up a directory, so it cancels out whatever the last directory was. For more information, look here: https://en.wikipedia.org/wiki/Path_(computing)#Unix_style

Corner Cases:

Did you consider the case where path = “/../”? In this case, you should return “/”. Another corner case is the path might contain multiple slashes ‘/’ together, such as “/home//foo/”. In this case, you should ignore redundant slashes and return “/home/foo”.

非常简单的模拟题,利用一个栈来储存当前的路径。用 “/” 将输入的全路径分割成多个部分,对于每一个部分循环处理:如果为空或者 “.” 则忽略,如果是 “..” ,则出栈顶部元素(如果栈为空则忽略),其他情况直接压入栈即可。

class Solution(object):
    def simplifyPath(self, path):
        """
        :type path: str
        :rtype: str
        """
        stack = []
        for part in path.split("/"):
            if part and part != ".": # 如果为空或者 "." 则忽略
                if part == "..":
                    if stack:
                        stack.pop()
                else:
                    stack.append(part)
        if not stack:
            return "/"
        else:
            return "/" + "/".join(stack)
# with stack
def simplifyPath1(self, path):
    stack = []
    for item in path.split("/"):
        if item not in [".", "..", ""]:
            stack.append(item)
        if item == ".." and stack:
            stack.pop()
    return "/" + "/".join(stack)

# with deque
def simplifyPath(self, path):
    deque = collections.deque()
    for item in path.split("/"):
        if item not in [".", "..", ""]:
            deque.append(item)
        if item == ".." and deque:
            deque.pop()
    return "/" + "/".join(deque)

93. Restore IP Addresses

Given a string containing only digits, restore it by returning all possible valid IP address combinations.

Example:

Input: "25525511135"
Output: ["255.255.11.135", "255.255.111.35"]
def restoreIpAddresses(self, s):
    res = []
    self.dfs(s, 4, 0, [], res)
    return res

def dfs(self, s, level, index, path, res):
    if level == 0:
        l = sum(map(len, path))
        if l < len(s):
            return  # backtracking
        else:
            res.append(".".join(path))
            return
    for i in xrange(1, 4):
        if index+i <= len(s) and self.valid(s[index:index+i]):
            self.dfs(s, level-1, index+i, path+[s[index:index+i]], res)

def valid(self, s):
    if len(s) == 2 and s[0] == "0":
        return False
    if len(s) == 3 and (s[0] == "0" or s > "255"):
        return False
    return True
def restoreIpAddresses(self, s):
    res = []
    self.dfs(s, 0, "", res)
    return res

def dfs(self, s, index, path, res):
    if index == 4:
        if not s:
            res.append(path[:-1])
        return # backtracking
    for i in xrange(1, 4):
        # the digits we choose should no more than the length of s
        if i <= len(s):
            #choose one digit
            if i == 1:
                self.dfs(s[i:], index+1, path+s[:i]+".", res)
            #choose two digits, the first one should not be "0"
            elif i == 2 and s[0] != "0":
                self.dfs(s[i:], index+1, path+s[:i]+".", res)
            #choose three digits, the first one should not be "0", and should less than 256
            elif i == 3 and s[0] != "0" and int(s[:3]) <= 255:
                self.dfs(s[i:], index+1, path+s[:i]+".", res)


def restoreIpAddresses(self, s):
    res = []
    self.dfs(s, 0, "", res)
    return res

def dfs(self, s, index, path, res):
    if index == 4:
        if not s:
            res.append(path[:-1])
        return # backtracking
    for i in xrange(1, 4):
        if i <= len(s):
            if int(s[:i]) <= 255:
                self.dfs(s[i:], index+1, path+s[:i]+".", res)
            if s[0] == "0":  # here should be careful
                break

208. Implement Trie (Prefix Tree)

Implement a trie with insert, search, and startsWith methods.

Example:

Trie trie = new Trie();

trie.insert("apple");
trie.search("apple");   // returns true
trie.search("app");     // returns false
trie.startsWith("app"); // returns true
trie.insert("app");
trie.search("app");     // returns true

Note:

You may assume that all inputs are consist of lowercase letters a-z. All inputs are guaranteed to be non-empty strings.

class TrieNode(object):
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.childs = dict()
        self.isWord = False



class Trie(object):

    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        """
        Inserts a word into the trie.
        :type word: str
        :rtype: void
        """
        node = self.root
        for letter in word:
            child = node.childs.get(letter)
            if child is None:
                child = TrieNode()
                node.childs[letter] = child
            node = child
        node.isWord = True

    def search(self, word):
        """
        Returns if the word is in the trie.
        :type word: str
        :rtype: bool
        """
        node = self.root
        for i in word:
            child = node.childs.get(i)
            if child is None:
                return False
            node = child
        return node.isWord


    def startsWith(self, prefix):
        """
        Returns if there is any word in the trie
        that starts with the given prefix.
        :type prefix: str
        :rtype: bool
        """
        node = self.root
        for letter in prefix:
            child = node.childs.get(letter)
            if child is None:
                return False
            node = child
        return True


# Your Trie object will be instantiated and called as such:
# trie = Trie()
# trie.insert("somestring")
# trie.search("key")
class TrieNode():
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.isWord = False

class Trie():
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        node = self.root
        for w in word:
            node = node.children[w]
        node.isWord = True

    def search(self, word):
        node = self.root
        for w in word:
            node = node.children.get(w)
            if not node:
                return False
        return node.isWord

211. Add and Search Word - Data structure design

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.

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.

class TrieNode():
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.isWord = False

class WordDictionary(object):
    def __init__(self):
        self.root = TrieNode()

    def addWord(self, word):
        node = self.root
        for w in word:
            node = node.children[w]
        node.isWord = True

    def search(self, word):
        node = self.root
        self.res = False
        self.dfs(node, word)
        return self.res

    def dfs(self, node, word):
        if not word:
            if node.isWord:
                self.res = True
            return
        if word[0] == ".":
            for n in node.children.values():
                self.dfs(n, word[1:])
        else:
            node = node.children.get(word[0])
            if not node:
                return
            self.dfs(node, word[1:])

24. Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head.

Example:

Given 1->2->3->4, you should return the list as 2->1->4->3.

Note:

Your algorithm should use only constant extra space. You may not modify the values in the list’s nodes, only nodes itself may be changed.

Good solution, here is a solution uses only one pointer: .. code-block:: python

def swapPairs(self, head):

dummy = p = ListNode(0) dummy.next = head while p.next and p.next.next:

tmp = head.next head.next = head.next.next tmp.next = head p.next = tmp # p = p.next.next # p = tmp.next p = head head = head.next

return dummy.next

# Iteratively
def swapPairs1(self, head):
    dummy = p = ListNode(0)
    dummy.next = head
    while head and head.next:
        tmp = head.next
        head.next = tmp.next
        tmp.next = head
        p.next = tmp
        head = head.next
        p = tmp.next
    return dummy.next

# Recursively
def swapPairs(self, head):
    if head and head.next:
        tmp = head.next
        head.next = self.swapPairs(tmp.next)
        tmp.next = head
        return tmp
    return head

# iteratively
def swapPairs1(self, head):
    if not head or not head.next:
        return head
    second = head.next
    pre = ListNode(0)
    while head and head.next:
        nxt = head.next
        head.next = nxt.next
        nxt.next = head
        pre.next = nxt
        head = head.next
        pre = nxt.next
    return second

# recursively
def swapPairs(self, head):
    if not head or not head.next:
        return head
    second = head.next
    head.next = self.swapPairs(second.next)
    second.next = head
    return second
# Iteratively
def swapPairs1(self, head):
    dummy = p = ListNode(0)
    dummy.next = head
    while head and head.next:
        tmp = head.next
        head.next = tmp.next
        tmp.next = head
        p.next = tmp
        head = head.next
        p = tmp.next
    return dummy.next

# Recursively
def swapPairs(self, head):
    if head and head.next:
        tmp = head.next
        head.next = self.swapPairs(tmp.next)
        tmp.next = head
        return tmp
    return head



# iteratively
def swapPairs1(self, head):
    if not head or not head.next:
        return head
    second = head.next
    pre = ListNode(0)
    while head and head.next:
        nxt = head.next
        head.next = nxt.next
        nxt.next = head
        pre.next = nxt
        head = head.next
        pre = nxt.next
    return second

# recursively
def swapPairs(self, head):
    if not head or not head.next:
        return head
    second = head.next
    head.next = self.swapPairs(second.next)
    second.next = head
    return second

179. Largest Number

Given a list of non negative integers, arrange them such that they form the largest number.

Example 1:

Input: [10,2]
Output: "210"

Example 2:

Input: [3,30,34,5,9]
Output: "9534330"

Note: The result may be very large, so you need to return a string instead of an integer.

“”” Replacement for built-in funciton cmp that was removed in Python 3

Compare the two objects x and y and return an integer according to the outcome. The return value is negative if x < y, zero if x == y and strictly positive if x > y. “”“

class Solution(object):
    def largestNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        nums = [str(num) for num in nums]
        nums.sort(cmp=lambda x, y: cmp(y+x, x+y))
        return ''.join(nums).lstrip('0') if ''.join(num).lstrip('0') else '0'

class Solution(object):
    def largestNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        nums = [str(num) for num in nums]
        nums.sort(cmp=lambda x, y: cmp(y+x, x+y))
        return ''.join(nums).lstrip('0') or '0'
# build-in function
def largestNumber1(self, nums):
    if not any(nums):
        return "0"
    return "".join(sorted(map(str, nums), cmp=lambda n1, n2: -1 if n1+n2>n2+n1 else (1 if n1+n2<n2+n1 else 0)))

# bubble sort
def largestNumber2(self, nums):
    for i in xrange(len(nums), 0, -1):
        for j in xrange(i-1):
            if not self.compare(nums[j], nums[j+1]):
                nums[j], nums[j+1] = nums[j+1], nums[j]
    return str(int("".join(map(str, nums))))

def compare(self, n1, n2):
    return str(n1) + str(n2) > str(n2) + str(n1)

# selection sort
def largestNumber3(self, nums):
    for i in xrange(len(nums), 0, -1):
        tmp = 0
        for j in xrange(i):
            if not self.compare(nums[j], nums[tmp]):
                tmp = j
        nums[tmp], nums[i-1] = nums[i-1], nums[tmp]
    return str(int("".join(map(str, nums))))

# insertion sort
def largestNumber4(self, nums):
    for i in xrange(len(nums)):
        pos, cur = i, nums[i]
        while pos > 0 and not self.compare(nums[pos-1], cur):
            nums[pos] = nums[pos-1]  # move one-step forward
            pos -= 1
        nums[pos] = cur
    return str(int("".join(map(str, nums))))

# merge sort
def largestNumber5(self, nums):
    nums = self.mergeSort(nums, 0, len(nums)-1)
    return str(int("".join(map(str, nums))))

def mergeSort(self, nums, l, r):
    if l > r:
        return
    if l == r:
        return [nums[l]]
    mid = l + (r-l)//2
    left = self.mergeSort(nums, l, mid)
    right = self.mergeSort(nums, mid+1, r)
    return self.merge(left, right)

def merge(self, l1, l2):
    res, i, j = [], 0, 0
    while i < len(l1) and j < len(l2):
        if not self.compare(l1[i], l2[j]):
            res.append(l2[j])
            j += 1
        else:
            res.append(l1[i])
            i += 1
    res.extend(l1[i:] or l2[j:])
    return res

# quick sort, in-place
def largestNumber(self, nums):
    self.quickSort(nums, 0, len(nums)-1)
    return str(int("".join(map(str, nums))))

def quickSort(self, nums, l, r):
    if l >= r:
        return
    pos = self.partition(nums, l, r)
    self.quickSort(nums, l, pos-1)
    self.quickSort(nums, pos+1, r)

def partition(self, nums, l, r):
    low = l
    while l < r:
        if self.compare(nums[l], nums[r]):
            nums[l], nums[low] = nums[low], nums[l]
            low += 1
        l += 1
    nums[low], nums[r] = nums[r], nums[low]
    return low
def partition(self, head, x):
    h1 = l1 = ListNode(0)
    h2 = l2 = ListNode(0)
    while head:
        if head.val < x:
            l1.next = head
            l1 = l1.next
        else:
            l2.next = head
            l2 = l2.next
        head = head.next
    l2.next = None
    l1.next = h2.next
    return h1.next





# choose the right-most element as pivot
def partition(self, nums, l, r):
    low = l
    while l < r:
        if nums[l] < nums[r]:
            nums[l], nums[low] = nums[low], nums[l]
            low += 1
        l += 1
    nums[low], nums[r] = nums[r], nums[low]
    return low

# Lomuto partition scheme
def partition(self, nums, l, r):
    pivot = nums[r]
    lo = l
    for i in xrange(l, r):
        if nums[i] < pivot:
            nums[i], nums[lo] = nums[lo], nums[i]
            lo += 1
    nums[lo], nums[r] = nums[r], nums[lo]
    return lo

228. Summary Ranges

Given a sorted integer array without duplicates, return the summary of its ranges.

Example 1:

Input:  [0,1,2,4,5,7]
Output: ["0->2","4->5","7"]
Explanation: 0,1,2 form a continuous range; 4,5 form a continuous range.

Example 2:

Input:  [0,2,3,4,6,8,9]
Output: ["0","2->4","6","8->9"]
Explanation: 2,3,4 form a continuous range; 8,9 form a continuous range.

Just collect the ranges, then format and return them.

class Solution(object):
    def summaryRanges(self, nums):
        """
        :type nums: List[int]
        :rtype: List[str]
        """
        ranges = []
        for i in nums:
            if not ranges or i > ranges[-1][-1] + 1:
                ranges += [],
            ranges[-1][1:] = i,
        return ['->'.join(map(str, r)) for r in ranges]
def summaryRanges(self, nums):
    if not nums:
        return []
    res, i, start = [], 0, 0
    while i < len(nums)-1:
        if nums[i]+1 != nums[i+1]:
            res.append(self.printRange(nums[start], nums[i]))
            start = i+1
        i += 1
    res.append(self.printRange(nums[start], nums[i]))
    return res

def printRange(self, l, r):
    if l == r:
        return str(l)
    else:
        return str(l) + "->" + str(r)