lintcode刷題筆記(一)

  最近開始刷lintcode,記錄下本身的答案,數字即爲lintcode題目號,語言爲python3,堅持日拱一卒吧。。。html

(一). 迴文字符竄問題(Palindrome problem)node

627. Longest Palindromepython

給出一個包含大小寫字母的字符串。求出由這些字母構成的最長的迴文串的長度是多少。git

數據是大小寫敏感的,也就是說,"Aa" 並不會被認爲是一個迴文串github

輸入 : s = "abccccdd"
輸出 : 7
說明 : 一種能夠構建出來的最長迴文串方案是 "dccaccd"。
#coding:utf-8

class Solution:
    """
    @param s: a string which consists of lowercase or uppercase letters
    @return: the length of the longest palindromes that can be built
    """
    def longestPalindrome(self, s):
        # write your code here
        char_set=set()
        for c in s:
            if c in char_set:
                char_set.remove(c) #出現偶數次的字母去除掉,留下出現奇數次
            else:
                char_set.add(c)
        single_count = len(char_set) 
        if single_count>0:
            single_count = single_count-1   #留一個單字母在迴文正中間
        return len(s)-single_count
if __name__=="__main__":
    s = Solution()
    print(s.longestPalindrome("abccccdd"))
627

 

200. Longest Palindromic Substring算法

Description

給出一個字符串(假設長度最長爲1000),求出它的最長迴文子串,你能夠假定只有一個知足條件的最長迴文串。express

Example

樣例 1:數組

輸入:"abcdzdcab"
輸出:"cdzdc"

樣例 2:markdown

輸入:"aba"
輸出:"aba"
#coding:utf-8

class Solution:
  
    def longestPalindrome(self, s):
        # write your code here
        length = len(s)
        sub="" if length>1 else s
        m = 0
        for i in range(length-1):
            len1,sub1 = expandAroundCenter(s,m,i,i)
            len2,sub2 = expandAroundCenter(s,m,i,i+1)
            if len1>m:
                m = len1
                sub = sub1
            if len2>m:
                m = len2
                sub = sub2
        return sub
                
def expandAroundCenter(s,m,i,j):
    sub=""
    while i>=0 and j<=len(s)-1:
        if s[i]==s[j]:
            if j-i+1>m:
                m = j-i+1
                sub = s[i:j+1]
            i=i-1
            j=j+1        
        else:
            break        
    return m,sub
        
if __name__=="__main__":
    s = Solution()
    print(s.longestPalindrome("abcdzdcab"))
    print(s.longestPalindrome("aba"))
    print(s.longestPalindrome("a"))
    print(s.longestPalindrome("ccc"))
    print(s.longestPalindrome("cc"))
    print(s.longestPalindrome("cccc"))
                
        
View Code

 

(二).  二分搜索法和log(n)算法(Binary Search & Log(n) Algorithm)數據結構

 

458. Last Position of Target

  給一個升序數組,找到 target 最後一次出現的位置,若是沒出現過返回 -1

  樣例 :

  輸入:nums = [1,2,2,4,5,5], target = 2
  輸出:2
  輸入:nums = [1,2,2,4,5,5], target = 6
  輸出:-1
#coding:utf-8

class Solution:
    #獲取最右邊的
    def lastPosition(self, nums, target):
        start = 0
        end = len(nums)-1
        index = -1
        while start<=end:
            mid = (start+end)//2
            if nums[mid]<=target:
                start = mid+1
            elif nums[mid]>target:
                end = mid-1
            
        if start>0 and nums[start-1]==target:
            index = start-1
        return index
    #獲取最左邊的    
    def firstPosition(self, nums, target):
        start = 0
        end = len(nums)-1
        index = -1
        while start<=end:
            mid = (start+end)//2
            if nums[mid]<target:
                start = mid+1
            elif nums[mid]>=target:
                end = mid-1
            
        if end<len(nums)-1 and nums[end+1]==target:
            index = end+1
        return index
        
if __name__=="__main__":
    s = Solution()
    print(s.lastPosition(nums = [], target = 10))
    print(s.lastPosition(nums = [1,2,2,4,5,5], target = 2))
    print(s.lastPosition(nums = [1,2,2,4,5,5], target = 6))
    print(s.lastPosition(nums = [1,2,2,2,2,2], target = 2))
    
    
    print(s.firstPosition(nums = [1,2,2,4,5,5], target = 2))
    print(s.firstPosition(nums = [1,2,2,4,5,5], target = 6))
    print(s.firstPosition(nums = [1,2,2,2,2,2], target = 2))
458

 

585. Maximum Number in Mountain Sequence

  給 n 個整數的山脈數組,即先增後減的序列,找到山頂(最大值)

Example

例1:

輸入: nums = [1, 2, 4, 8, 6, 3] 
輸出: 8

例2:

輸入: nums = [10, 9, 8, 7], 
輸出: 10
#coding:utf-8

class Solution:

    def mountainSequence(self, nums):
        # write your code here
        if len(nums)==1:
            return nums[0]
        for i in range(len(nums)-1):
            if nums[i+1]<nums[i]:
                return nums[i]
                
585

 

460. Find K Closest Elements

Description

  給一個目標數 target, 一個非負整數 k, 一個按照升序排列的數組 A。在A中找與target最接近的k個整數。返回這k個數並按照與target的接近程度從小到大排序,若是接近程度至關,那麼小的數排在前面。

  1. k是一個非負整數,而且老是小於已排序數組的長度。
  2. 給定數組的長度是正整數, 不會超過 10^44​​
  3. 數組中元素的絕對值不會超過 10^44​​

Example

樣例 1:

輸入: A = [1, 2, 3], target = 2, k = 3
輸出: [2, 1, 3]

樣例 2:

輸入: A = [1, 4, 6, 8], target = 3, k = 3
輸出: [4, 1, 6]
class Solution:
    """
    @param A: an integer array
    @param target: An integer
    @param k: An integer
    @return: an integer array
    """
    def kClosestNumbers(self, A, target, k):
        # write your code here
        sub=100000
        nearest=-1
        start = 0
        end = len(A)-1
        while start<=end:
            mid = (start+end)//2
            temp = abs(A[mid]-target)
            if temp<sub:
                sub = temp
                nearest = mid
            if A[mid]>target:
                end = mid-1
            elif A[mid]<target:
                start = mid+1
            elif A[mid]==target:
                break
        out=[]
        if nearest!=-1 and k>0:
            out.append(A[nearest])
            i=1
            left,right=nearest-1,nearest+1
            while left>=0 and right<=len(A)-1 and i<k:
                if abs(A[left]-target)<=abs(A[right]-target):
                    out.append(A[left])
                    left = left-1
                else:
                    out.append(A[right])
                    right = right+1
                i = i+1
                
            if i<k and left<0:
                out.extend(A[right:right+k-i])
            if i<k and right>len(A)-1:
                out.extend(A[left:left-(k-i):-1])
        return out
if __name__=="__main__":
    s = Solution()
    print(s.kClosestNumbers( A = [1, 2, 3], target = 2, k = 3))
    print(s.kClosestNumbers(A = [1, 4, 6, 8], target = 3, k = 3))
    print(s.kClosestNumbers(A = [1,4,6,10,20], target = 21, k = 4))
    print(s.kClosestNumbers(A = [1,2,4,5,6,7,8,10], target = 5, k = 0))
    print(s.kClosestNumbers(A = [1,4,8,12,16,28,38], target = 12, k = 4))
    print(s.kClosestNumbers(A = [1,4,6,8], target = 3, k = 3))
            
460

 

428. Pow(x,n)

  實現 pow(x, n). (n是一個整數,不用擔憂精度,當答案和標準輸出差絕對值小於1e-3時都算正確)

Example

樣例 1:

輸入: x = 9.88023, n = 3
輸出: 964.498

樣例 2:

輸入: x = 2.1, n = 3
輸出: 9.261

樣例 3:

輸入: x = 1, n = 0
輸出: 1
#coding:utf-8


class Solution:

    def myPow(self,x,n):
        if n==0:
            return 1
        elif n<0:
            x = 1/x
            n = -n
        return recursive_pow(x,n)
            
def recursive_pow(x,n):            
    if n==1:
        return x
    else:
        half = recursive_pow(x,n//2)
        if n%2==1:
            return half*half*x
        else:
            return half*half
            
if __name__=="__main__":
    s = Solution()
    print(s.myPow(x = 9.88023, n = 3))
    print(s.myPow(x = 2.1, n = 3))
    print(s.myPow( x = 1, n = 0))
    print(s.myPow( x = 2.00000, n = -2147483648))
428

 

159.Find Minimum Rotated Sorted Array

  假設一個排好序的數組在其某一未知點發生了旋轉(好比0 1 2 4 5 6 7 可能變成4 5 6 7 0 1 2)。你須要找到其中最小的元素

Example

Example 1:

輸入:[4, 5, 6, 7, 0, 1, 2]
輸出:0
解釋:
數組中的最小值爲0

Example 2:

輸入:[2,1]
輸出:1
解釋:
數組中的最小值爲1
#coding:utf-8
class Solution:
   
    def findMin(self, nums):
        
        length = len(nums)
        if length==1:
            return nums[0]
        elif length>1:
            if nums[0]<nums[-1]:
                return nums[0]
            else:
                left,right = 0,length-1
                while left<right:
                    mid = (left+right)//2
                    if nums[mid]>nums[left]:
                        left = mid
                    elif nums[mid]<nums[left]:
                        right = mid
                    else:              #mid和left相等時
                        break
            return nums[right]
if __name__=="__main__":
    s = Solution()
    print(s.findMin([4, 5, 6, 7, 0, 1, 2]))
    print(s.findMin([2,1]))
                    
159

 

140. Fast Power

  計算an % b其中a,b和n都是32位的非負整數。

Example

例如 231 % 3 = 2

例如 1001000 % 1000 = 0

Challenge

O(logn)

#coding:utf-8

#原理: (A*B)%p = ((A%p)*(B%p))%p

"""
@param a: A 32bit integer
@param b: A 32bit integer
@param n: A 32bit integer
@return: An integer
 """
class Solution:
  
    def fastPower(self, a, b, n):
        if n==0:
            return 1%b
        elif n==1:
            return a%b
        else:
            half_remainder = self.fastPower(a,b,n//2)
            if n%2==1:
                return (half_remainder*half_remainder*a)%b
            else:
                return (half_remainder*half_remainder)%b
if __name__=="__main__":
    s = Solution()
    print(s.fastPower(2,3,31))
    print(s.fastPower(3,1,0))
    print(s.fastPower(100,1000,1000))
140

 

75. Find Peak Elements

  你給出一個整數數組(size爲n),其具備如下特色:

  • 相鄰位置的數字是不一樣的
  • A[0] < A[1] 而且 A[n - 2] > A[n - 1]

假定P是峯值的位置則知足A[P] > A[P-1]A[P] > A[P+1],返回數組中任意一個峯值的位置。

  • 數組保證至少存在一個峯
  • 若是數組存在多個峯,返回其中任意一個就行
  • 數組至少包含 3 個

Example

樣例 1:
	輸入:  [1, 2, 1, 3, 4, 5, 7, 6]
	輸出:  1 or 6
	
	解釋:
	返回峯頂元素的下標


樣例 2:
	輸入: [1,2,3,4,1]
	輸出:  3
#coding:utf-8

#參考題解:https://leetcode-cn.com/problems/find-peak-element/solution/hua-jie-suan-fa-162-xun-zhao-feng-zhi-by-guanpengc/
#注意峯值的方向,先上升後降低

"""
@param A: An integers array.
@return: return any of peek positions.
"""
class Solution:

    def findPeak(self, A):
        # write your code here
        length = len(A)
        if length==1:
            return 0
        elif length>2:
            left,right = 0, length-2
            while left<right:
                mid = (left+right)//2
                if A[mid]>A[mid+1]:  #降低趨勢
                    right = mid
                elif A[mid]<A[mid+1]: #上升趨勢
                    left = mid+1
            return left
if __name__=="__main__":
    s = Solution()
    print(s.findPeak([1, 2, 1, 3, 4, 5, 7, 6]))
    print(s.findPeak([1,2,3,4,1]))
    
                
75

 

74. First Bad Version

  代碼庫的版本號是從 1 到 n 的整數。某一天,有人提交了錯誤版本的代碼,所以形成自身及以後版本的代碼在單元測試中均出錯。請找出第一個錯誤的版本號。

你能夠經過 isBadVersion 的接口來判斷版本號 version 是否在單元測試中出錯,具體接口詳情和調用方法請見代碼的註釋部分。

Example

n = 5: isBadVersion(3) -> false isBadVersion(5) -> true isBadVersion(4) -> true 所以能夠肯定第四個版本是第一個錯誤版本。

Challenge

調用 isBadVersion 的次數越少越好

Example

n = 5:

    isBadVersion(3) -> false
    isBadVersion(5) -> true
    isBadVersion(4) -> true

所以能夠肯定第四個版本是第一個錯誤版本。

Challenge

調用 isBadVersion 的次數越少越好
74

 

 62. Search in Rotated Sorted Array

  假設有一個排序的按未知的旋轉軸旋轉的數組(好比,0 1 2 4 5 6 7 可能成爲4 5 6 7 0 1 2)。給定一個目標值進行搜索,若是在數組中找到目標值返回數組中的索引位置,不然返回-1。你能夠假設數組中不存在重複的元素。

Example

例1:

輸入: [4, 5, 1, 2, 3] and target=1, 
輸出: 2.

例2:

輸入: [4, 5, 1, 2, 3] and target=0, 
輸出: -1.

Challenge

O(logN) 時間限制

class Solution:
    """
    @param A: an integer rotated sorted array
    @param target: an integer to be searched
    @return: an integer
    """
    def search(self, A, target):
        # write your code here
        length = len(A)
        if length>0:
            left,right=0,length-1
            if A[0]==target:
                return 0
            elif A[0]>target:
                while left<=right:
                    mid=(left+right)//2
                    if A[0]<=A[mid]:
                        left = mid+1
                    else:
                        if A[mid]>target:
                            right = mid-1
                        elif A[mid]<target:
                            left = mid+1
                        else:
                            return mid
            else:
                while left<=right:
                    mid=(left+right)//2
                    if A[0]>=A[mid]:
                        right=mid-1
                    else:
                        if A[mid]>target:
                            right = mid-1
                        elif A[mid]<target:
                            left = mid+1
                        else:
                            return mid
        return -1
if __name__=="__main__":
    s = Solution()
    print(s.search([4, 5, 1, 2, 3],1))
    print(s.search([4, 5, 1, 2, 3],0))
    print(s.search([4, 3],3))
                
            
62

 

(三). 雙指針問題(Two Pointers)

 

 228. Middle of Linked List

  找鏈表的中點。

Example

樣例 1:

輸入:  1->2->3
輸出: 2	
樣例解釋: 返回中間節點的值

樣例 2:

輸入:  1->2
輸出: 1	
樣例解釋: 若是長度是偶數,則返回中間偏左的節點的值。

Challenge

若是鏈表是一個數據流,你能夠不從新遍歷鏈表的狀況下獲得中點麼?

#coding:utf-8


#Definition of ListNode
class ListNode(object):
    def __init__(self, val, next=None):
        self.val = val
        self.next = next

"""
@param head: the head of linked list.
@return: a middle node of the linked list
"""
class Solution:
    
    def middleNode(self, head):
        # write your code here
        slow = fast = head
        if head:
            while fast.next!=None and fast.next.next!=None:
                slow = slow.next
                fast = fast.next.next
        return slow
if __name__=="__main__":
    s = Solution()
    list1 = ListNode(1,ListNode(2,ListNode(3)))
    list2 = ListNode(1,ListNode(2))
    print(s.middleNode(list1).val)
    print(s.middleNode(list2).val)
228

 

607 Two Sum III -Data structure design

  設計b並實現一個 TwoSum 類。他須要支持如下操做:addfind
    add -把這個數添加到內部的數據結構。
    find -是否存在任意一對數字之和等於這個值

Example

樣例 1:

add(1);add(3);add(5);
find(4)//返回true
find(7)//返回false
#coding:utf-8

#思路:遍歷字典,求sum和遍歷元素的差, 判斷差是否也在字典中
class TwoSum:
    """
    @param number: An integer
    @return: nothing
    """
    def __init__(self):
        self.numbers=dict()
        
    def add(self, number):
        # write your code here
        if number not in self.numbers:
            self.numbers[number]=1
        else:
            self.numbers[number]+=1

    """
    @param value: An integer
    @return: Find if there exists any pair of numbers which sum is equal to the value.
    """
    def find(self, value):
        # write your code here
        for key in self.numbers:
            target = value-key
            if target in self.numbers:
                if target!=key or self.numbers[target]>1:
                    return True
        return False


#按順序插入列表,find時先後指針遍歷
# class TwoSum:
    # """
    # @param number: An integer
    # @return: nothing
    # """
    # def __init__(self):
        # self.numbers=[]
        
    # def add(self, number):
        # # write your code here
        # length = len(self.numbers)
        # if length==0:
            # self.numbers.append(number)
        # for i in range(length):
            # if self.numbers[i]>number:
                # self.numbers.insert(i,number)
                # break
        # if len(self.numbers)==length:
            # self.numbers.append(number)

    # """
    # @param value: An integer
    # @return: Find if there exists any pair of numbers which sum is equal to the value.
    # """
    # def find(self, value):
        # # write your code here
        # i,j=0,len(self.numbers)-1
        # while i<j:
            # if self.numbers[i]+self.numbers[j]==value:
                # return True
            # elif self.numbers[i]+self.numbers[j]>value:
                # j = j-1
            # else:
                # i = i+1
        # return False
if __name__=="__main__":
    s = TwoSum()
    # s.add(1)
    # s.add(3)
    # s.add(5)
    # print(s.find(4))
    # print(s.find(7))
    
    # s.add(2)
    # s.add(3)
    # print(s.find(4))
    # print(s.find(5))
    # print(s.find(6))
    # s.add(3)
    # print(s.find(6))
    
    s.add(2)
    s.add(2)
    s.add(2)
    print(s.find(6))
    s.add(2)
    print(s.find(4))
    print(s.find(5))
    s.add(1)
    print(s.find(2))
    print(s.find(3))
    
    
607

 

539. Move Zeros

  給一個數組 nums 寫一個函數將 0 移動到數組的最後面,非零元素保持原數組的順序

    1.必須在原數組上操做
    2.最小化操做數

Example

例1:

輸入: nums = [0, 1, 0, 3, 12],
輸出: [1, 3, 12, 0, 0].

例2:

輸入: nums = [0, 0, 0, 3, 1],
輸出: [3, 1, 0, 0, 0].
#coding:utf-8


"""
思路:
快慢指針:假設咱們有一個新數組,有 2 根指針分別從老數組和新數組從前日後走,稱老數組上的指針爲「讀指針」,新數組上的指針爲「寫指針」;只有當讀指針所指向的數值非0時,纔將讀指針所指的數值寫入到寫指針所指的空間上,而後兩根指針再繼續向前走;當老數組遍歷完時,只要將新數組繼續填 0 直到新老數組長度一致便可。題目要求「就地操做」,那麼實際上就不須要開這個新數組,只要讓兩根指針都在原數組上往前走就行:這是由於,讀指針因爲會跳過非 0 空間,其掃描速度遠快於寫指針,全部被讀指針掃描過的非零值都會經過寫指針寫入「新的空間」中,所以全部被寫指針覆蓋掉的非零值,以前一定已經保存過了。該方法時間複雜度 O(n),空間複雜度 O(1)
"""

"""
@param nums: an integer array
@return: nothing
"""
class Solution:
    
    def moveZeroes(self, nums):
        # write your code here
        i=j=0
        while i<len(nums):
            if nums[i]!=0:
                nums[j]=nums[i]
                j = j+1
            i = i+1
        while j<i:
            nums[j]=0
            j = j+1
        return nums
if __name__=="__main__":
    s = Solution()
    print(s.moveZeroes([0, 1, 0, 3, 12]))
    print(s.moveZeroes([0, 0, 0, 3, 1]))
539

 

521 Remove Duplicate Numbers in Array

  給一個整數數組,去除重複的元素。

  你應該作這些事

    1.在原數組上操做
    2.將去除重複以後的元素放在數組的開頭
    3.返回去除重複元素以後的元素個數

Example

例1:

輸入:
nums = [1,3,1,4,4,2]
輸出:
(nums變爲[1,3,4,2,?,?])
4

解釋:
1. 將重複的整數移動到 nums 的尾部 => nums = [1,3,4,2,?,?].
2. 返回 nums 中惟一整數的數量  => 4.
事實上咱們並不關心你把什麼放在了 ? 處, 只關心沒有重複整數的部分.

例2:

輸入:
nums = [1,2,3]
輸出: 
(nums變爲[1,2,3]) 3
[1,2,3]
#coding:utf-8


"""
@param nums: an array of integers
@return: the number of unique integers
"""

#時間複雜度O(n),空間複雜度O(n)
class Solution:
    
    def deduplication(self, nums):
        # write your code here
        nums_set=set()
        i=0
        for num in nums:
            if num not in nums_set:
                nums_set.add(num)
                nums[i]=num
                i = i+1
                
        return i 
        
        
        

#排序後使用雙指針,時間複雜度O(nlogn),空間複雜度O(1)
# class Solution:
    
    # def deduplication(self, nums):
        # # write your code here
        # length = len(nums)
        # if length<=1:
            # return length
        # quicksort(nums,0,length-1)
        # i=j = 1
        # while i<length:
            # if nums[i]!=nums[i-1]:
                # nums[j]=nums[i]
                # j = j+1
            # i = i+1
        # return j
        
        
# def quicksort(nums,start,end):
    # if start<end:
        # pivot = start
        # left,right=start+1,end
        # while left<=right:
            # while left<=right and nums[left]<=nums[pivot]:
                # left = left+1
            # while left<=right and nums[right]>nums[pivot]:
                # right= right-1
            # if left<=right:
                # nums[left],nums[right]=nums[right],nums[left]
        # nums[right],nums[pivot]=nums[pivot],nums[right]
        # quicksort(nums,start,right-1)
        # quicksort(nums,right+1,end)
        
if __name__=="__main__":
    
    s = Solution()
    print(s.deduplication([1,3,1,4,4,2]))
    print(s.deduplication(nums = [1,2,3]))
521

 

464 Sort Integers II

  給一組整數,請將其在原地按照升序排序。使用歸併排序,快速排序,堆排序或者任何其餘 O(n log n) 的排序算法。

Description

中文
English

給一組整數,請將其在原地按照升序排序。使用歸併排序,快速排序,堆排序或者任何其餘 O(n log n) 的排序算法。

Example

例1:

輸入:[3,2,1,4,5],
輸出:[1,2,3,4,5]。

例2:

輸入:[2,3,1],
輸出:[1,2,3]。
"""
@param A: an integer array
@return: nothing
"""
class Solution:
    
    def sortIntegers2(self, A):
        # write your code here
        quicksort(A,0,len(A)-1)
        return A

def quicksort(alist,start,end):
    if start<end:
        pivot=alist[start]
        left,right = start,end
        while left<right:
            while left<right and alist[right]>=pivot:
                right-=1
            alist[left],alist[right]=alist[right],alist[left]
            while left<right and alist[left]<=pivot:
                left+=1
            alist[right],alist[left]=alist[left],alist[right]
        quicksort(alist,start,left-1)
        quicksort(alist,left+1,end)
if __name__=="__main__":
    s = Solution()
    print(s.sortIntegers2([3, 2, 1, 4, 5]))
    print(s.sortIntegers2([2, 3, 1]))
464

 

608. Two Sum II- Input array is sorted

  給定一個已經 按升序排列 的數組,找到兩個數使他們加起來的和等於特定數。
  函數應該返回這兩個數的下標,index1必須小於index2。注意返回的值不是 0-based

Example

例1:

輸入: nums = [2, 7, 11, 15], target = 9 
輸出: [1, 2]

例2:

輸入: nums = [2,3], target = 5
輸出: [1, 2]
class Solution:
    """
    @param nums: an array of Integer
    @param target: target = nums[index1] + nums[index2]
    @return: [index1 + 1, index2 + 1] (index1 < index2)
    """
    def twoSum(self, nums, target):
        # write your code here
        length = len(nums)
        if length>1:
            i,j=0,length-1
            while i<j:
                if nums[i]+nums[j]==target:
                    return i+1,j+1
                elif nums[i]+nums[j]<target:
                    i+=1
                else:
                    j-=1
if __name__=="__main__":
    s = Solution()
    print(s.twoSum(nums = [2, 7, 11, 15], target = 9 ))
    print(s.twoSum(nums = [2,3], target = 5 ))
608

 

143 Sort Colors II

  給定一個有n個對象(包括k種不一樣的顏色,並按照1到k進行編號)的數組,將對象進行分類使相同顏色的對象相鄰,並按照1,2,...k的順序進行排序。

  1. 不能使用代碼庫中的排序函數來解決這個問題
  2. k <= n

Example

樣例1

輸入: 
[3,2,2,1,4] 
4
輸出: 
[1,2,2,3,4]

樣例2

輸入: 
[2,1,1,2,2] 
2
輸出: 
[1,1,2,2,2]

Challenge

一個至關直接的解決方案是使用計數排序掃描2遍的算法。這樣你會花費O(k)的額外空間。你否能在不使用額外空間的狀況下完成?

#coding:utf-8

#思路參考:https://www.cnblogs.com/libaoquan/p/7226211.html (計數排序/桶排序改進)
#輸入[3,2,2,1,4],進行一次遍歷後變化過程以下:
# [3, 2, 2, 1, 4]
# [2, 2, -1, 1, 4]
# [2, -1, -1, 1, 4]
# [0, -2, -1, 1, 4]
# [-1, -2, -1, 0, 4]
# [-1, -2, -1, -1, 0]


"""
@param colors: A list of integer
@param k: An integer
@return: nothing
"""
class Solution:
    
    def sortColors2(self, colors, k):
        length = len(colors)
        if length<=1:
            return colors
        #統計計數
        for i in range(length):
            while colors[i]>0:
                index = colors[i]
                if colors[index-1]>0:
                    colors[i]=colors[index-1]
                    colors[index-1]=-1         #表示index出現一次
                elif colors[index-1]<=0:
                    colors[i]=0
                    colors[index-1]-=1         #表示index再次出現
        
        #輸出排序結果
        j=length-1
        for i in range(k-1,-1,-1):
            temp = colors[i]
            while temp<0:
                colors[j]=i+1
                temp+=1
                j-=1
        return colors
if __name__=="__main__":
    s = Solution()
    print(s.sortColors2([3,2,2,1,4],4))
    print(s.sortColors2([2,1,1,2,2],2))
        
        
143

 

57. Three Sum


Description:
    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
    Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
    The solution set must not contain duplicate triplets.

Example 1:
    Input:[2,7,11,15]
    Output:[]
    
Example 2:
    Input:[-1,0,1,2,-1,-4]
    Output:    [[-1, 0, 1],[-1, -1, 2]]

#coding:utf-8

"""
題目:57 Three Sum
Description:
    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
    Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
    The solution set must not contain duplicate triplets.

Example 1:
    Input:[2,7,11,15]
    Output:[]
    
Example 2:
    Input:[-1,0,1,2,-1,-4]
    Output:    [[-1, 0, 1],[-1, -1, 2]]
"""


"""
思路:
因爲設置了三個變量,故時間複雜度最少是O(n^2)
在開頭固定一個變量,而後一前一後 移動指針
和大於零 後指針前移
和小於零 前指針後移
和等於零 放入結果中,再讓先後指針移動
"""

"""
@param numbers: Give an array numbers of n integer
@return: Find all unique triplets in the array which gives the sum of zero.
"""
class Solution:
    
    def threeSum(self, numbers):
        # write your code here
        length = len(numbers)
        ret=[]
        if length<3:
            return ret
        quicksort(numbers,0,length-1)
        print(numbers)
        for k in range(length-2):
            if k==0 or numbers[k]!=numbers[k-1]:  #防止重複
                twoSum(numbers,-numbers[k],start=k+1,end=length-1,ret=ret)
        return ret

def quicksort(numbers,start,end):
    if start<end:
        left,right=start,end
        pivot = numbers[start]
        while left<right:
            while left<right and numbers[right]>=pivot:
                right-=1
            numbers[right],numbers[left]=numbers[left],numbers[right]
            while left<right and numbers[left]<pivot:
                left+=1
            numbers[right],numbers[left]=numbers[left],numbers[right]
        quicksort(numbers,start,right-1)
        quicksort(numbers,right+1,end)
        
def twoSum(numbers,target,start,end,ret):
    i,j = start,end
    while i<j:
        if numbers[i]+numbers[j]<target:
            i+=1
        elif numbers[i]+numbers[j]>target:
            j-=1
        else:
            if (-target)<numbers[i]:
                temp=[-target,numbers[i],numbers[j]]
            elif (-target)>numbers[j]:
                temp=[numbers[i],numbers[j],-target]
            else:
                temp=[numbers[i],-target,numbers[j]]
            if temp not in ret: #防止重複
                ret.append(temp)
            i+=1
            j-=1

if __name__=="__main__":
    s = Solution()
    # print(s.threeSum([2,7,11,15]))
    # print(s.threeSum([-1,0,1,2,-1,-4]))
    # print(s.threeSum([1,0,-1,-1,-1,-1,0,1,1,1]))
    print(s.threeSum([-2,-3,-4,-5,-100,99,1,4,4,4,5,1,0,-1,2,3,4,5]))
            
57

 

31.Partition Array

Description
    Given an array nums of integers and an int k, partition the array (i.e move the elements in "nums") such that:

        All elements < k are moved to the left
        All elements >= k are moved to the right

    Return the partitioning index, i.e the first index i nums[i] >= k.
    You should do really partition in array nums instead of just counting the numbers of integers smaller than k.
    If all elements in nums are smaller than k, then return nums.length

Example 1:
    Input:
    [],9
    Output:
    0

Example 2:
    Input:
    [3,2,2,1],2
    Output:1
    Explanation:
    the real array is[1,2,2,3].So return 1

Challenge
    Can you partition the array in-place and in O(n)?

#coding:utf-8

"""
Description
    Given an array nums of integers and an int k, partition the array (i.e move the elements in "nums") such that:

        All elements < k are moved to the left
        All elements >= k are moved to the right

    Return the partitioning index, i.e the first index i nums[i] >= k.
    You should do really partition in array nums instead of just counting the numbers of integers smaller than k.
    If all elements in nums are smaller than k, then return nums.length

Example 1:
    Input:
    [],9
    Output:
    0

Example 2:
    Input:
    [3,2,2,1],2
    Output:1
    Explanation:
    the real array is[1,2,2,3].So return 1

Challenge
    Can you partition the array in-place and in O(n)?
"""

"""
思路:相似於快速排序的左右指針
"""

class Solution:
    """
    @param nums: The integer array you should partition
    @param k: An integer
    @return: The index after partition
    """
    def partitionArray(self, nums, k):
        # write your code here
        length=len(nums)
        if length==0:
            return 0
        i,j=0,length-1
        while i<=j:
            while i<=j and nums[i]<k:
                i+=1
            while i<=j and nums[j]>=k:
                j-=1
            if i<j:
                nums[i],nums[j]=nums[j],nums[i]
        return i
if __name__=="__main__":
    s = Solution()
    print(s.partitionArray([],9))
    print(s.partitionArray([3,2,2,1],2))
        
31

 

5. Kth Largest Element
Description

    Find K-th largest element in an array.
    You can swap elements in the array

Example 1:
    Input:
    n = 1, nums = [1,3,4,2]
    Output:
    4

Example 2:
    Input:
    n = 3, nums = [9,3,2,4,8]
    Output:
    4

Challenge
    O(n) time, O(1) extra memory.

#coding:utf-8

"""
題目:5. Kth Largest Element
Description

    Find K-th largest element in an array.
    You can swap elements in the array

Example 1:
    Input:
    n = 1, nums = [1,3,4,2]
    Output:
    4

Example 2:
    Input:
    n = 3, nums = [9,3,2,4,8]
    Output:
    4

Challenge
    O(n) time, O(1) extra memory.
"""
"""
思路:
    快速選擇算法 的平均時間複雜度爲 O(N){O}(N)O(N)。就像快速排序那樣,本算法也是 Tony Hoare 發明的,所以也被稱爲 Hoare選擇算法。

本方法大體上與快速排序相同。簡便起見,注意到第 k 個最大元素也就是第 N - k 個最小元素,所以能夠用第 k 小算法來解決本問題。

首先,咱們選擇一個樞軸,並在線性時間內定義其在排序數組中的位置。這能夠經過 劃分算法 的幫助來完成。

    爲了實現劃分,沿着數組移動,將每一個元素與樞軸進行比較,並將小於樞軸的全部元素移動到樞軸的左側。

這樣,在輸出的數組中,樞軸達到其合適位置。全部小於樞軸的元素都在其左側,全部大於或等於的元素都在其右側。

這樣,數組就被分紅了兩部分。若是是快速排序算法,會在這裏遞歸地對兩部分進行快速排序,時間複雜度爲 O(Nlog⁡N)。

而在這裏,因爲知道要找的第 N - k 小的元素在哪部分中,咱們不須要對兩部分都作處理,這樣就將平均時間複雜度降低到 O(N)。

"""
class Solution:
    """
    @param n: An integer
    @param nums: An array
    @return: the Kth largest element
    """
    def kthLargestElement(self, n, nums):
        # write your code here
        length = len(nums)
        if n>length or n==0:
            return None
        return half_quicksort(nums,n,0,length-1)
        
    
    #方法二,利用二叉堆
    def kthLargestElement2(self, n, nums):
        import heapq
        length = len(nums)
        if n>length or n==0:
            return None
        return heapq.nlargest(n,nums)[n-1]
        
def half_quicksort(nums,k,start,end):
    if k==1 and start==end:
        return nums[start]
    if start<end:
        left,right=start,end
        pivot = nums[start]
        while left<right:
            while left<right and nums[right]>=pivot:
                right-=1
            nums[left],nums[right]=nums[right],nums[left]
            while left<right and nums[left]<pivot:
                left+=1
            nums[left],nums[right]=nums[right],nums[left]
        
        if end-right>k-1:
            return half_quicksort(nums,k,right+1,end)
        elif end-right<k-1:
            return half_quicksort(nums,k-(end-right+1),start,right-1)
        else:
            return nums[right]
            
if __name__=="__main__":
    s = Solution()
    print(s.kthLargestElement(n = 1, nums = [1,3,4,2]))
    print(s.kthLargestElement(n = 3, nums = [9,3,2,4,8]))
    
    print(s.kthLargestElement2(n = 1, nums = [1,3,4,2]))
    print(s.kthLargestElement2(n = 3, nums = [9,3,2,4,8]))
        
         
5

 

(四). 寬度優先搜索和拓撲排序(BFS and Topplogical Sort)

 

433. Number of Islands

Description

  Given a boolean 2D matrix, 0 is represented as the sea, 1 is represented as the island. If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent.
        Find the number of islands.

Example 1:
    Input:
    [
      [1,1,0,0,0],
      [0,1,0,0,1],
      [0,0,0,1,1],
      [0,0,0,0,0],
      [0,0,0,0,1]
    ]
    Output:3

Example 2:

    Input:
    [
      [1,1]
    ]
    Output:1

#coding:utf-8


"""
433. Number of Islands

    Given a boolean 2D matrix, 0 is represented as the sea, 1 is represented as the island. If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent.

    Find the number of islands.
    Example

Example 1:
    Input:
    [
      [1,1,0,0,0],
      [0,1,0,0,1],
      [0,0,0,1,1],
      [0,0,0,0,0],
      [0,0,0,0,1]
    ]
    Output:3

Example 2:

    Input:
    [
      [1,1]
    ]
    Output:1
"""
"""
思路:線性掃描整個二維網格,若是一個結點包含 1,則以其爲根結點啓動深度優先搜索。在深度優先搜索過程當中,每一個訪問過的結點被標記爲 0。計數啓動深度優先搜索的根結點的數量,即爲島嶼的數量。
"""
class Solution:
    """
    @param grid: a boolean 2D matrix
    @return: an integer
    """
    def numIslands(self, grid):
        # write your code here
        rows = len(grid)
        nums = 0
        if rows==0:
            return nums
        for r in range(rows):
            cols = len(grid[r])
            if cols>0:
                for c in range(cols):
                    if grid[r][c]==1:
                        dfs(grid,r,c)
                        nums+=1
        return nums

def dfs(grid,r,c):
    rows = len(grid)
    if r<0 or r>rows-1:
        return
        
    cols = len(grid[r])
    if c<0 or c>cols-1:
        return
    if grid[r][c]==0:
        return
    grid[r][c]=0   #grid[r][c]=1,將其由1設置爲0,表示已經遍歷
    dfs(grid,r-1,c)
    dfs(grid,r+1,c)
    dfs(grid,r,c-1)
    dfs(grid,r,c+1)

if __name__=="__main__":
    s = Solution()
    g1 =[
      [1,1,0,0,0],
      [0,1,0,0,1],
      [0,0,0,1,1],
      [0,0,0,0,0],
      [0,0,0,0,1]
    ]
    g2=[
      [1,1]
    ]
    print(s.numIslands(g1))
    print(s.numIslands(g2))
    
433

69. Binary Tree Level Order Traversal

Description
    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).

        The first data is the root node, followed by the value of the left and right son nodes, and "#" indicates that there is no child node.
        The number of nodes does not exceed 20.

Example 1:

    Input:{1,2,3}
    Output:[[1],[2,3]]
    Explanation:
      1
     / \
    2   3
    it will be serialized {1,2,3}
    level order traversal

Example 2:

    Input:{1,#,2,3}
    Output:[[1],[2],[3]]
    Explanation:
    1
     \
      2
     /
    3
    it will be serialized {1,#,2,3}
    level order traversal

Challenge
    Challenge 1: Using only 1 queue to implement it.
    Challenge 2: Use BFS algorithm to do it.

#coding:utf-8

"""
題目:69. Binary Tree Level Order Traversal
Description
    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).

        The first data is the root node, followed by the value of the left and right son nodes, and "#" indicates that there is no child node.
        The number of nodes does not exceed 20.

Example 1:

    Input:{1,2,3}
    Output:[[1],[2,3]]
    Explanation:
      1
     / \
    2   3
    it will be serialized {1,2,3}
    level order traversal

Example 2:

    Input:{1,#,2,3}
    Output:[[1],[2],[3]]
    Explanation:
    1
     \
      2
     /
    3
    it will be serialized {1,#,2,3}
    level order traversal

Challenge
    Challenge 1: Using only 1 queue to implement it.
    Challenge 2: Use BFS algorithm to do it.
"""


#Definition of TreeNode:
class TreeNode:
    def __init__(self, val,left=None,right=None):
        self.val = val
        self.left, self.right = left, right


class Solution:
    """
    @param root: A Tree
    @return: Level order a list of lists of integer
    """
    def levelOrder(self, root):
        # write your code here
        if not root:
            return []
        q=[[root]]
        ret=[]
        while q:
            val,temp=[],[]
            cur_list = q.pop(0)
            for cur in cur_list:
                if cur.left:
                    temp.append(cur.left)
                if cur.right:
                    temp.append(cur.right)
                if cur.val!="#":
                    val.append(cur.val)
            if temp:
                q.append(temp)
            if val:
                ret.append(val)
        return ret
                
if __name__=="__main__":
    s = Solution()
    #{1,2,3}
    t1 = TreeNode(1,TreeNode(2),TreeNode(3))
    print(s.levelOrder(t1))
    #{1,#,2,3}
    t2 = TreeNode(1,TreeNode("#"),TreeNode(2,TreeNode(3)))
    print(s.levelOrder(t2))
            
        
        
69

 

615 Course Schedule


Description

    There are a total of n courses you have to take, labeled from 0 to n - 1.
    Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
    Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

Example 1:
    Input: n = 2, prerequisites = [[1,0]]
    Output: true

Example 2:
    Input: n = 2, prerequisites = [[1,0],[0,1]]
    Output: false

#coding:utf-8

"""
Description

    There are a total of n courses you have to take, labeled from 0 to n - 1.
    Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
    Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

Example 1:
    Input: n = 2, prerequisites = [[1,0]] 
    Output: true

Example 2:
    Input: n = 2, prerequisites = [[1,0],[0,1]] 
    Output: false
"""

#思路:參考https://leetcode-cn.com/problems/course-schedule/solution/tuo-bu-pai-xu-by-liweiwei1419/
"""
拓撲排序
具體作以下:

1、在開始排序前,掃描對應的存儲空間(使用鄰接表),將入度爲 0 的結點放入隊列。

2、只要隊列非空,就從隊首取出入度爲 0 的結點,將這個結點輸出到結果集中,而且將這個結點的全部鄰接結點(它指向的結點)的入度減 111,在減 111 之後,若是這個被減 111 的結點的入度爲 000 ,就繼續入隊。

3、當隊列爲空的時候,檢查結果集中的頂點個數是否和課程數相等便可。

"""

class Solution:
    """
    @param: numCourses: a total of n courses
    @param: prerequisites: a list of prerequisite pairs
    @return: true if can finish all courses or false
    """
    def canFinish(self, numCourses, prerequisites):
        # write your code here
        length = len(prerequisites)
        if length==0:
            return True
        
        #初始化入度和鄰接表(鄰接表存放的是後繼 successor 結點的集合)
        degree = [0 for i in range(numCourses)]
        adj = [set() for i in range(numCourses)]
        
        # 想要學習課程 0 ,你須要先完成課程 1 ,咱們用一個匹配來表示他們: [0,1] 
        # [0, 1] 表示 1 在先,0 在後,1的後繼節點爲0  (因此0這個節點的度加一)
        for second, first in prerequisites:
            if second not in adj[first]:  #避免重複
                degree[second]+=1
                adj[first].add(second)
        
    
        p=[]
        count = 0
        for i in range(len(degree)):
            if degree[i]==0:
                p.append(i)
        while p:
            cur = p.pop()
            for j in adj[cur]:
                degree[j]-=1
                if degree[j]==0:
                    p.append(j)
            count+=1
        if count==numCourses:
            return True
        return False
if __name__=="__main__":
    s = Solution()
    # print(s.canFinish(2, prerequisites = [[1,0]] ))
    # print(s.canFinish(2, prerequisites = [[1,0],[0,1]] ))
    print(s.canFinish(10, prerequisites = [[5,8],[3,5],[1,9],[4,5],[0,2],[1,9],[7,8],[4,9]] ))
            
            
                
        
        
        
        
        
615

 

615 Course Schedule II

Description
    There are a total of n courses you have to take, labeled from 0 to n - 1.
    Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

    Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.

    There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.
    Have you met this question in a real interview?  
    Example

Example 1:
    Input: n = 2, prerequisites = [[1,0]]
    Output: [0,1]

Example 2:
    Input: n = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
    Output: [0,1,2,3] or [0,2,1,3]

#coding:utf-8

"""
Description
    There are a total of n courses you have to take, labeled from 0 to n - 1.
    Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

    Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.

    There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.
    Have you met this question in a real interview?  
    Example

Example 1:
    Input: n = 2, prerequisites = [[1,0]] 
    Output: [0,1]

Example 2:
    Input: n = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]] 
    Output: [0,1,2,3] or [0,2,1,3]
"""


class Solution:
    """
    @param: numCourses: a total of n courses
    @param: prerequisites: a list of prerequisite pairs
    @return: the course order
    """
    def findOrder(self, numCourses, prerequisites):
        # write your code here
        length = len(prerequisites)
        if length==0:
            return [i for i in range(numCourses)]
        
        #初始化入度和鄰接表(鄰接表存放的是後繼 successor 結點的集合)
        degree = [0 for i in range(numCourses)]
        adj = [set() for i in range(numCourses)]
        
        # 想要學習課程 0 ,你須要先完成課程 1 ,咱們用一個匹配來表示他們: [0,1] 
        # [0, 1] 表示 1 在先,0 在後,1的後繼節點爲0  (因此0這個節點的度加一)
        for second, first in prerequisites:
            if second not in adj[first]:  #避免重複
                degree[second]+=1
                adj[first].add(second)
        
        p=[]
        course = []
        for i in range(len(degree)):
            if degree[i]==0:
                p.append(i)
        while p:
            cur = p.pop()
            for j in adj[cur]:
                degree[j]-=1
                if degree[j]==0:
                    p.append(j)
            course.append(cur)
        if len(course)==numCourses:
            return course
        return []
        
if __name__=="__main__":
    s = Solution()
    print(s.findOrder(2, prerequisites = [[1,0]] ))
    print(s.findOrder(4, prerequisites = [[1,0],[2,0],[3,1],[3,2]] ))
        
616

 

605 Sequence Reconstruction

Description
    Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. The org sequence is a permutation of the integers from 1 to n, with 1 ≤ n ≤ 10^4.
    Reconstruction means building a shortest common supersequence of the sequences in seqs (i.e., a shortest sequence so that all sequences in seqs are subsequences of it).
    Determine whether there is only one sequence that can be reconstructed from seqs and it is the org sequence.

Example 1:
    Input:org = [1,2,3], seqs = [[1,2],[1,3]]
    Output: false
    Explanation:
    [1,2,3] is not the only one sequence that can be reconstructed, because [1,3,2] is also a valid sequence that can be reconstructed.

Example 2:
    Input: org = [1,2,3], seqs = [[1,2]]
    Output: false
    Explanation:
    The reconstructed sequence can only be [1,2].

Example 3:
    Input: org = [1,2,3], seqs = [[1,2],[1,3],[2,3]]
    Output: true
    Explanation:
    The sequences [1,2], [1,3], and [2,3] can uniquely reconstruct the original sequence [1,2,3].

Example 4:
    Input:org = [4,1,5,2,6,3], seqs = [[5,2,6,3],[4,1,5,2]]
    Output:true

#coding:utf-8
"""
Description
    Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. The org sequence is a permutation of the integers from 1 to n, with 1 ≤ n ≤ 10^4. 
    Reconstruction means building a shortest common supersequence of the sequences in seqs (i.e., a shortest sequence so that all sequences in seqs are subsequences of it). 
    Determine whether there is only one sequence that can be reconstructed from seqs and it is the org sequence.

Example 1:
    Input:org = [1,2,3], seqs = [[1,2],[1,3]]
    Output: false
    Explanation:
    [1,2,3] is not the only one sequence that can be reconstructed, because [1,3,2] is also a valid sequence that can be reconstructed.

Example 2:
    Input: org = [1,2,3], seqs = [[1,2]]
    Output: false
    Explanation:
    The reconstructed sequence can only be [1,2].

Example 3:
    Input: org = [1,2,3], seqs = [[1,2],[1,3],[2,3]]
    Output: true
    Explanation:
    The sequences [1,2], [1,3], and [2,3] can uniquely reconstruct the original sequence [1,2,3].

Example 4:
    Input:org = [4,1,5,2,6,3], seqs = [[5,2,6,3],[4,1,5,2]]
    Output:true

"""
# 拓撲排序:構建圖和入度,按順序遍歷,驗證惟一性
# 拓撲排序的四種問法:
    # 求任意一個拓撲排序。
    # 問是否存在拓撲排序(course schedule 1 )
    # 求全部拓撲排序(DFS)
    # 求是否存在且僅存在一個拓撲排序 (Queue中最多隻有一個節點)

class Solution:
    """
    @param org: a permutation of the integers from 1 to n
    @param seqs: a list of sequences
    @return: true if it can be reconstructed only one or false
    """
    def sequenceReconstruction(self, org, seqs):
        # write your code here
        from collections import defaultdict
        # if len(seqs)==0 or len(org)==0:
            # return False
        
        degree=dict()
        adj=defaultdict(set)
        for seq in seqs:
            for i in range(0,len(seq)):
                if seq[i] not in degree:
                    degree[seq[i]]=0
                if i+1<len(seq) and seq[i+1] not in adj[seq[i]]:
                    adj[seq[i]].add(seq[i+1])
                    if seq[i+1] not in degree:
                        degree[seq[i+1]]=1
                    else:
                        degree[seq[i+1]]+=1
        
        q=[i for i in degree.keys() if degree[i]==0]
        ret=[]
        while q:
            cur = q.pop()
            for cur_adj in adj[cur]:
                degree[cur_adj]-=1
                if degree[cur_adj]==0:
                    q.append(cur_adj)
            ret.append(cur)
        if ret==org:      #可能有多個順序,若相等則是惟一性
            return True
        return False
if __name__=="__main__":
    s = Solution()
    print(s.sequenceReconstruction(org = [], seqs = [[]]))
    print(s.sequenceReconstruction(org = [1,2,3], seqs = [[1,2],[1,3]]))
    print(s.sequenceReconstruction(org = [1,2,3], seqs = [[1,2]]))
    print(s.sequenceReconstruction(org = [1,2,3], seqs = [[1,2],[1,3],[2,3]]))
    print(s.sequenceReconstruction(org = [4,1,5,2,6,3], seqs = [[5,2,6,3],[4,1,5,2]]))
            
        
            
            
605

137 Clone Graph
Description
    Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. Nodes are labeled uniquely.
    You need to return a deep copied graph, which has the same structure as the original graph,
    and any changes to the new graph will not have any effect on the original graph.

Clarification:

    {1,2,4#2,1,4#3,5#4,1,2#5,3} represents follow graph:

    1------2  3
     \     |  |
      \    |  |
       \   |  |
        \  |  |
          4   5

    we use # to split each node information.
    1,2,4 represents that 2, 4 are 1's neighbors
    2,1,4 represents that 1, 4 are 2's neighbors
    3,5 represents that 5 is 3's neighbor
    4,1,2 represents that 1, 2 are 4's neighbors
    5,3 represents that 3 is 5's neighbor

Example1
    Input:
    {1,2,4#2,1,4#4,1,2}
    Output:
    {1,2,4#2,1,4#4,1,2}
    Explanation:
    1------2  
     \     |  
      \    |  
       \   |  
        \  |  
          4   

#coding:utf

"""
137 Clone Graph
Description
    Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. Nodes are labeled uniquely.
    You need to return a deep copied graph, which has the same structure as the original graph, 
    and any changes to the new graph will not have any effect on the original graph.

Clarification:

    {1,2,4#2,1,4#3,5#4,1,2#5,3} represents follow graph:

    1------2  3
     \     |  | 
      \    |  |
       \   |  |
        \  |  |
          4   5

    we use # to split each node information.
    1,2,4 represents that 2, 4 are 1's neighbors
    2,1,4 represents that 1, 4 are 2's neighbors
    3,5 represents that 5 is 3's neighbor
    4,1,2 represents that 1, 2 are 4's neighbors
    5,3 represents that 3 is 5's neighbor

Example1
    Input:
    {1,2,4#2,1,4#4,1,2}
    Output: 
    {1,2,4#2,1,4#4,1,2}
    Explanation:
    1------2  
     \     |  
      \    |  
       \   |  
        \  |  
          4   

"""

"""
Definition for a undirected graph node
"""
class UndirectedGraphNode:
    def __init__(self, x):
        self.label = x
        self.neighbors = []

"""
@param: node: A undirected graph node
@return: A undirected graph node
"""
class Solution:
    
    def cloneGraph(self, node):
        if node==None:
            return node
        root = node
        nodes=[]
        q={node}
        while q:
            cur = q.pop()
            nodes.append(cur)
            for i in cur.neighbors:
                if i not in nodes:
                    q.add(i)    
        # print(nodes)
        map=dict()
        for n in nodes:
            map[n]=UndirectedGraphNode(n.label)
            
        for n in nodes:
            temp = map[n]
            for ner in n.neighbors:
                temp.neighbors.append(map[ner])
                
        return map[root]
if __name__=="__main__":
    node = UndirectedGraphNode(0)
    node.neighbors.append(UndirectedGraphNode(0))
    node.neighbors.append(UndirectedGraphNode(0))
    s = Solution()
    print(s.cloneGraph(node))

        
137

 127. Topological Sorting

Description

    Given an directed graph, a topological order of the graph nodes is defined as follow:
        For each directed edge A -> B in graph, A must before B in the order list.
        The first node in the order can be any node in the graph with no nodes direct to it.

Clarification:

    {1,2,4#2,1,4#3,5#4,1,2#5,3} represents follow graph:

    1------2  3
     \     |  |
      \    |  |
       \   |  |
        \  |  |
          4   5

    we use # to split each node information.
    1,2,4 represents that 2, 4 are 1's neighbors
    2,1,4 represents that 1, 4 are 2's neighbors
    3,5 represents that 5 is 3's neighbor
    4,1,2 represents that 1, 2 are 4's neighbors
    5,3 represents that 3 is 5's neighbor
    
The topological order can be:

    [0, 1, 2, 3, 4, 5]
    [0, 2, 3, 1, 5, 4]
    ...

Challenge
    Can you do it in both BFS and DFS?

#coding:utf
"""
127. Topological Sorting

Description

    Given an directed graph, a topological order of the graph nodes is defined as follow:
        For each directed edge A -> B in graph, A must before B in the order list.
        The first node in the order can be any node in the graph with no nodes direct to it.

Clarification:

    {1,2,4#2,1,4#3,5#4,1,2#5,3} represents follow graph:

    1------2  3
     \     |  | 
      \    |  |
       \   |  |
        \  |  |
          4   5

    we use # to split each node information.
    1,2,4 represents that 2, 4 are 1's neighbors
    2,1,4 represents that 1, 4 are 2's neighbors
    3,5 represents that 5 is 3's neighbor
    4,1,2 represents that 1, 2 are 4's neighbors
    5,3 represents that 3 is 5's neighbor
    
The topological order can be:

    [0, 1, 2, 3, 4, 5]
    [0, 2, 3, 1, 5, 4]
    ...

Challenge
    Can you do it in both BFS and DFS?

"""

"""
Definition for a Directed graph node
class DirectedGraphNode:
    def __init__(self, x):
        self.label = x
        self.neighbors = []
"""


class Solution:
    """
    @param: graph: A list of Directed graph node
    @return: Any topological order for the given graph.
    """
    def topSort(self, graph):
        # write your code here
        if len(graph)==0:
            return graph
        degree=dict()
        seen=set()
        for node in graph:
            if node not in seen:
                seen.add(node)
                if node not in degree:
                    degree[node]=0
                for nb in node.neighbors:
                    if nb not in degree:
                        degree[nb]=1
                    else:
                        degree[nb]+=1
        order=[]
        while seen:
            node =seen.pop()
            if degree[node]==0:
                order.append(node)
                for nb in node.neighbors:
                    degree[nb]-=1
            else:
                seen.add(node)
        return order
            
                
                
                    
                
        
                    
                
        
        
        
127

7. Serialize and Deserialize Binary Tree


Description

    Design an algorithm and write code to serialize and deserialize a binary tree.
    Writing the tree to a file is called 'serialization' and reading back from the file to reconstruct the exact same binary tree is 'deserialization'.

    There is no limit of how you deserialize or serialize a binary tree,
    LintCode will take your output of serialize as the input of deserialize, it won't check the result of serialize.

Example 1:

    Input:{3,9,20,#,#,15,7}
    Output:{3,9,20,#,#,15,7}
    Explanation:
    Binary tree {3,9,20,#,#,15,7},  denote the following structure:
          3
         / \
        9  20
          /  \
         15   7
    it will be serialized {3,9,20,#,#,15,7}

Example 2:

    Input:{1,2,3}
    Output:{1,2,3}
    Explanation:
    Binary tree {1,2,3},  denote the following structure:
       1
      / \
     2   3
    it will be serialized {1,2,3}

Our data serialization use BFS traversal. This is just for when you got Wrong Answer and want to debug the input.

You can use other method to do serializaiton and deserialization.

#coding:utf-8

"""
7. Serialize and Deserialize Binary Tree
Description

    Design an algorithm and write code to serialize and deserialize a binary tree. 
    Writing the tree to a file is called 'serialization' and reading back from the file to reconstruct the exact same binary tree is 'deserialization'.

    There is no limit of how you deserialize or serialize a binary tree, 
    LintCode will take your output of serialize as the input of deserialize, it won't check the result of serialize.

Example 1:

    Input:{3,9,20,#,#,15,7}
    Output:{3,9,20,#,#,15,7}
    Explanation:
    Binary tree {3,9,20,#,#,15,7},  denote the following structure:
          3
         / \
        9  20
          /  \
         15   7
    it will be serialized {3,9,20,#,#,15,7}

Example 2:

    Input:{1,2,3}
    Output:{1,2,3}
    Explanation:
    Binary tree {1,2,3},  denote the following structure:
       1
      / \
     2   3
    it will be serialized {1,2,3}

Our data serialization use BFS traversal. This is just for when you got Wrong Answer and want to debug the input.

You can use other method to do serializaiton and deserialization.

"""

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""


class Solution:
    """
    @param root: An object of TreeNode, denote the root of the binary tree.
    This method will be invoked first, you should design your own algorithm 
    to serialize a binary tree which denote by a root node to a string which
    can be easily deserialized by your own "deserialize" method later.
    """
    def serialize(self, root):
        # write your code here
        if root==None:
            return root
        ret=[root.val]
        q=[root]
        while q:
            cur = q.pop(0)
            if cur.left!=None:
                q.append(cur.left)
                ret.append(cur.left.val)
            else:
                ret.append("#")
            if cur.right!=None:
                q.append(cur.right)
                ret.append(cur.right.val)
            else:
                ret.append("#")
        return ret

    """
    @param data: A string serialized by your serialize method.
    This method will be invoked second, the argument data is what exactly
    you serialized at method "serialize", that means the data is not given by
    system, it's given by your own serialize method. So the format of data is
    designed by yourself, and deserialize it here as you serialize it in 
    "serialize" method.
    """
    def deserialize(self, data):
        # write your code here
        if data==None or len(data)==0:
            return None
        
        root = TreeNode(data[0])   
        length=len(data)
        q=[root]
        i=1
        while i<length and q:
            node = q.pop(0)
            if data[i]!="#":
                node.left = TreeNode(data[i])
                q.append(node.left)
            else:
                node.left=None
            if i+1<length and data[i+1]!="#" :
                node.right = TreeNode(data[i+1])
                q.append(node.right)
            else:
                node.right=None
            i+=2
        return root
                
            
7

 

120. Word Ladder


Description
    Given two words (start and end), and a dictionary, find the shortest transformation sequence from start to end, output the length of the sequence.
    Transformation rule such that:

        Only one letter can be changed at a time
        Each intermediate word must exist in the dictionary. (Start and end words do not need to appear in the dictionary )

        Return 0 if there is no such transformation sequence.
        All words have the same length.
        All words contain only lowercase alphabetic characters.
        You may assume no duplicates in the word list.
        You may assume beginWord and endWord are non-empty and are not the same.

Example 1:
    Input:start = "a",end = "c",dict =["a","b","c"]
    Output:2
    Explanation:
    "a"->"c"

Example 2:
    Input:start ="hit",end = "cog",dict =["hot","dot","dog","lot","log"]
    Output:5
    Explanation:
    "hit"->"hot"->"dot"->"dog"->"cog"

#coding:utf-8

"""
120. Word Ladder
Description
    Given two words (start and end), and a dictionary, find the shortest transformation sequence from start to end, output the length of the sequence.
    Transformation rule such that:

        Only one letter can be changed at a time
        Each intermediate word must exist in the dictionary. (Start and end words do not need to appear in the dictionary )

        Return 0 if there is no such transformation sequence.
        All words have the same length.
        All words contain only lowercase alphabetic characters.
        You may assume no duplicates in the word list.
        You may assume beginWord and endWord are non-empty and are not the same.

Example 1:
    Input:start = "a",end = "c",dict =["a","b","c"]
    Output:2
    Explanation:
    "a"->"c"

Example 2:
    Input:start ="hit",end = "cog",dict =["hot","dot","dog","lot","log"]
    Output:5
    Explanation:
    "hit"->"hot"->"dot"->"dog"->"cog"


"""
#參考:https://leetcode-cn.com/problems/word-ladder/solution/dan-ci-jie-long-by-leetcode/

class Solution:
    """
    @param: start: a string
    @param: end: a string
    @param: dict: a set of string
    @return: An integer
    """
    def ladderLength(self, start, end, dict):
        # write your code here
        if (not start) or (not end) or len(dict)==0:
            return 0

        #構建圖
        from collections import defaultdict
        graph = defaultdict(list)
        if start not in dict:
            dict.add(start)
        if end not in dict:
            dict.add(end)
        for word in dict:
            for i in range(len(word)):
                graph[word[:i]+"*"+word[i+1:]].append(word)
            
        q=[(start,1)]
        seen=set()
        #Breadth first search
        while q:
            cur,level = q.pop(0)
            
            for i in range(len(cur)):
                temp = cur[:i]+"*"+cur[i+1:]
                for ner in graph[temp]:
                    if ner==end:
                        return level+1
                    if ner not in seen:
                        q.append((ner,level+1))
                        seen.add(ner)
                # graph[temp]=[]
        return 0    
        


# class Solution:
    # """
    # @param: start: a string
    # @param: end: a string
    # @param: dict: a set of string
    # @return: An integer
    # """
    # def ladderLength(self, start, end, dict):
        # # write your code here
        # if (not start) or (not end) or len(dict)==0:
            # return 0
        
        # #構建圖
        # from collections import defaultdict
        # graph = defaultdict(list)
        # if start not in dict:
            # dict.append(start)
        # if end not in dict:
            # dict.append(end)
        # for i in dict:
            # for j in dict:
                # if i!=j and change_one(i,j):
                    # graph[i].append(j)
        
        # q=[(start,1)]
        # seen=set()
        # order=[]
        # #Breadth first search
        # while q:
            # cur,level = q.pop(0)
            # for word in graph[cur]:
                # if word==end:
                    # return level+1
                # if word not in seen:
                    # q.append((word,level+1))
                    # seen.add(word)
        # return 0    
        
# def change_one(i,j):
    # length=len(i)
    # for n in range(length):
        # if i[:n]==j[:n] and i[n+1:]==j[n+1:]:
            # return True

if __name__=="__main__":
    s = Solution()
    print(s.ladderLength(start = "a",end = "c",dict ={"a","b","c"}))
    print(s.ladderLength(start ="hit",end = "cog",dict ={"hot","dot","dog","lot","log"}))

        
120

 

(五).  二叉樹問題(Binary tree problem)

900. Closest Binary Search Tree Value

Description:

    Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.
    Given target value is a floating point.
    You are guaranteed to have only one unique value in the BST that is closest to the target.


Example1
    Input: root = {5,4,9,2,#,8,10} and target = 6.124780
    Output: 5
    Explanation:
    Binary tree {5,4,9,2,#,8,10},  denote the following structure:
            5
           / \
         4    9
        /    / \
       2    8  10

Example2
    Input: root = {3,2,4,1} and target = 4.142857
    Output: 4
    Explanation:
    Binary tree {3,2,4,1},  denote the following structure:
         3
        / \
      2    4
     /
    1

#coding:utf-8

"""
900. Closest Binary Search Tree Value

Description:

    Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.
    Given target value is a floating point.
    You are guaranteed to have only one unique value in the BST that is closest to the target.


Example1
    Input: root = {5,4,9,2,#,8,10} and target = 6.124780
    Output: 5
    Explanation:
    Binary tree {5,4,9,2,#,8,10},  denote the following structure:
            5
           / \
         4    9
        /    / \
       2    8  10

Example2
    Input: root = {3,2,4,1} and target = 4.142857
    Output: 4
    Explanation:
    Binary tree {3,2,4,1},  denote the following structure:
         3
        / \
      2    4
     /
    1

"""


"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param root: the given BST
    @param target: the given target
    @return: the value in the BST that is closest to the target
    """
    def closestValue(self, root, target):
        # write your code here

        if root==None or target==None:
            return None
            
        ret,dif =root.val,abs(root.val-target)
        q=[root]
        while q:
            cur = q.pop(0)
            temp=abs(cur.val-target)
            if temp<dif:
                dif=temp
                ret = cur.val
            if cur.left !=None:
                q.append(cur.left)
            if cur.right !=None:
                q.append(cur.right)
        return ret
900

 

596. Minimum Subtree

Description

    Given a binary tree, find the subtree with minimum sum. Return the root of the subtree.

    LintCode will print the subtree which root is your return node.
    It's guaranteed that there is only one subtree with minimum sum and the given binary tree is not an empty tree.

Example 1:

    Input:
    {1,-5,2,1,2,-4,-5}
    Output:1
    Explanation:
    The tree is look like this:
         1
       /   \
     -5     2
     / \   /  \
    1   2 -4  -5
    The sum of whole tree is minimum, so return the root.

Example 2:

    Input:
    {1}
    Output:1
    Explanation:
    The tree is look like this:
       1
    There is one and only one subtree in the tree. So we return 1.

#coding:utf-8

#https://www.lintcode.com/problem/minimum-subtree/description
"""
596. Minimum Subtree

Description

    Given a binary tree, find the subtree with minimum sum. Return the root of the subtree.

    LintCode will print the subtree which root is your return node.
    It's guaranteed that there is only one subtree with minimum sum and the given binary tree is not an empty tree.

Example 1:

    Input:
    {1,-5,2,1,2,-4,-5}
    Output:1
    Explanation:
    The tree is look like this:
         1
       /   \
     -5     2
     / \   /  \
    1   2 -4  -5 
    The sum of whole tree is minimum, so return the root.

Example 2:

    Input:
    {1}
    Output:1
    Explanation:
    The tree is look like this:
       1
    There is one and only one subtree in the tree. So we return 1.

"""

#Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None

class Solution:
    """
    @param root: the root of binary tree
    @return: the root of the minimum subtree
    """
    import sys
    def __init__(self):
        self.ret=None
        self.minimum=sys.maxsize
    def findSubtree(self, root):
        # write your code here
        if root==None:
            return root
        self.cal_min_sum(root)
        # print(Solution.ret.val)
        return self.ret
        
    def cal_min_sum(self,node):
        if node==None:
            return 0
        temp = node.val+self.cal_min_sum(node.left)+self.cal_min_sum(node.right)
        if temp<self.minimum:
            self.minimum=temp
            self.ret=node
        return temp  #必須得返回
                
if __name__=="__main__":

    s = Solution()
    # root = TreeNode(1)
    # root.left,root.right=TreeNode(-5),TreeNode(2)
    # root.left.left,root.left.right = TreeNode(1),TreeNode(2)
    # root.right.left,root.right.right = TreeNode(-4),TreeNode(-5)
    root = TreeNode(1)
    root.right=TreeNode(2)
    print(s.findSubtree(root))
596

 

480 Binary Tree Pathss


Description

    Given a binary tree, return all root-to-leaf paths.

Example 1:

    Input:{1,2,3,#,5}
    Output:["1->2->5","1->3"]
    Explanation:
       1
     /   \
    2     3
     \
      5

Example 2:

    Input:{1,2}
    Output:["1->2"]
    Explanation:
       1
     /   
    2  

#coding:utf-8

"""
480 Binary Tree Pathss
Description

    Given a binary tree, return all root-to-leaf paths.

Example 1:

    Input:{1,2,3,#,5}
    Output:["1->2->5","1->3"]
    Explanation:
       1
     /   \
    2     3
     \
      5

Example 2:

    Input:{1,2}
    Output:["1->2"]
    Explanation:
       1
     /   
    2     

"""

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""
"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param root: the root of the binary tree
    @return: all root-to-leaf paths
    """
    def binaryTreePaths(self, root):
        # write your code here
        if root==None:
            return []
        paths=[]
        self.helper(root,paths,"")
        return paths
                
    def helper(self,node,paths,tree):
        if node.left==None and node.right==None:
            paths.append(tree+str(node.val))
        if node.left!=None:
            self.helper(node.left,paths,tree+str(node.val)+"->")
        if node.right!=None:
            self.helper(node.right,paths,tree+str(node.val)+"->")
480

 

453. Flatten Binary Tree to Linked List

Description
    Flatten a binary tree to a fake "linked list" in pre-order traversal.
    Here we use the right pointer in TreeNode as the next pointer in ListNode.
    Don't forget to mark the left child of each node to null. Or you will get Time Limit Exceeded or Memory Limit Exceeded.

Example 1:

    Input:{1,2,5,3,4,#,6}
    Output:{1,#,2,#,3,#,4,#,5,#,6}
    Explanation:
         1
        / \
       2   5
      / \   \
     3   4   6

    1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

Example 2:

    Input:{1}
    Output:{1}
    Explanation:
             1
             1

Challenge
    Do it in-place without any extra memory.

#coding:utf-8

"""
453. Flatten Binary Tree to Linked List

Description
    Flatten a binary tree to a fake "linked list" in pre-order traversal.
    Here we use the right pointer in TreeNode as the next pointer in ListNode.
    Don't forget to mark the left child of each node to null. Or you will get Time Limit Exceeded or Memory Limit Exceeded.

Example 1:

    Input:{1,2,5,3,4,#,6}
    Output:{1,#,2,#,3,#,4,#,5,#,6}
    Explanation:
         1
        / \
       2   5
      / \   \
     3   4   6

    1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

Example 2:

    Input:{1}
    Output:{1}
    Explanation:
             1
             1

Challenge
    Do it in-place without any extra memory.

"""
#參考:https://blog.csdn.net/c070363/article/details/51203408

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param root: a TreeNode, the root of the binary tree
    @return: nothing
    """
    def flatten(self, root):
        # write your code here
        node = root
        while node:
            if node.left!=None:
                temp = node.left
                while temp.right:
                    temp = temp.right
                temp.right = node.right
                node.right = node.left
                node.left=None
            node = node.right
        return root
453

 

93. Balanced Binary Tree
Description

Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

Example  1:
    Input: tree = {1,2,3}
    Output: true
    
    Explanation:
    This is a balanced binary tree.
          1  
         / \                
        2  3

    
Example  2:
    Input: tree = {3,9,20,#,#,15,7}
    Output: true
    
    Explanation:
    This is a balanced binary tree.
          3  
         / \                
        9  20                
          /  \                
         15   7

    
Example  3:
    Input: tree = {1,#,2,3,4}
    Output: false
    
    Explanation:
    This is not a balanced tree.
    The height of node 1's right sub-tree is 2 but left sub-tree is 0.
          1  
           \                
           2                
          /  \                
         3   4

#coding:utf-8

"""
93. Balanced Binary Tree
Description

Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

Example  1:
    Input: tree = {1,2,3}
    Output: true
    
    Explanation:
    This is a balanced binary tree.
          1  
         / \                
        2  3

    
Example  2:
    Input: tree = {3,9,20,#,#,15,7}
    Output: true
    
    Explanation:
    This is a balanced binary tree.
          3  
         / \                
        9  20                
          /  \                
         15   7 

    
Example  3:
    Input: tree = {1,#,2,3,4}
    Output: false
    
    Explanation:
    This is not a balanced tree. 
    The height of node 1's right sub-tree is 2 but left sub-tree is 0.
          1  
           \                
           2                
          /  \                
         3   4

"""
#參考:https://www.jiuzhang.com/solutions/balanced-binary-tree/#tag-highlight-lang-python

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param root: The root of binary tree.
    @return: True if this Binary tree is Balanced, or false.
    """
    def isBalanced(self, root):
        # write your code here
        
        balanced,_ = self.cal_balance(root)
        return balanced
        
    def cal_balance(self,node):
        if node==None:
            return True,0
        balanced,leftHeight = self.cal_balance(node.left)
        if not balanced:
            return False,0
        balanced,rightHeight = self.cal_balance(node.right)
        if not balanced:
            return False,0
        dif = abs(leftHeight-rightHeight)
        return dif<=1,max(leftHeight,rightHeight)+1
        
93

 

902. Kth Smallest Element in a BST
Description
    Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.

    You may assume k is always valid, 1 ≤ k ≤ BST's total elements.

Example 1:

    Input:{1,#,2},2
    Output:2
    Explanation:
        1
         \
          2
    The second smallest element is 2.

Example 2:

    Input:{2,1,3},1
    Output:1
    Explanation:
      2
     / \
    1   3
    The first smallest element is 1.

Challenge

    What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?

#coding:utf-8
"""
902. Kth Smallest Element in a BST
Description
    Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.

    You may assume k is always valid, 1 ≤ k ≤ BST's total elements.

Example 1:

    Input:{1,#,2},2
    Output:2
    Explanation:
        1
         \
          2
    The second smallest element is 2.

Example 2:

    Input:{2,1,3},1
    Output:1
    Explanation:
      2
     / \
    1   3
    The first smallest element is 1.

Challenge

    What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?

"""

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param root: the given BST
    @param k: the given k
    @return: the kth smallest element in BST
    """
    def kthSmallest(self, root, k):
        # write your code here
        if root==None:
            return None
        vals=[]
        self.findElement(root,vals)
        return vals[k-1]
        
    def findElement(self,node,vals):
        if node==None:
            return 
        self.findElement(node.left,vals)
        vals.append(node.val)
        self.findElement(node.right,vals)
902

 

578. Lowest Common Ancestor III
Description

    Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes.
    The lowest common ancestor is the node with largest depth which is the ancestor of both nodes.
    Return null if LCA does not exist.

    node A or node B may not exist in tree.

Example1

    Input:
    {4, 3, 7, #, #, 5, 6}
    3 5
    5 6
    6 7
    5 8
    Output:
    4
    7
    7
    null
    Explanation:
      4
     / \
    3   7
       / \
      5   6

    LCA(3, 5) = 4
    LCA(5, 6) = 7
    LCA(6, 7) = 7
    LCA(5, 8) = null

Example2

    Input:
    {1}
    1 1
    Output:
    1
    Explanation:
    The tree is just a node, whose value is 1.

#coding:utf-8
"""
578. Lowest Common Ancestor III
Description

    Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes.
    The lowest common ancestor is the node with largest depth which is the ancestor of both nodes.
    Return null if LCA does not exist.

    node A or node B may not exist in tree.

Example1

    Input: 
    {4, 3, 7, #, #, 5, 6}
    3 5
    5 6
    6 7 
    5 8
    Output: 
    4
    7
    7
    null
    Explanation:
      4
     / \
    3   7
       / \
      5   6

    LCA(3, 5) = 4
    LCA(5, 6) = 7
    LCA(6, 7) = 7
    LCA(5, 8) = null

Example2

    Input:
    {1}
    1 1
    Output: 
    1
    Explanation:
    The tree is just a node, whose value is 1.


"""

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        this.val = val
        this.left, this.right = None, None
"""


class Solution:
    """
    @param: root: The root of the binary tree.
    @param: A: A TreeNode
    @param: B: A TreeNode
    @return: Return the LCA of the two nodes.
    """
    def lowestCommonAncestor3(self, root, A, B):
        # write your code here
        if root==None:
            return root
        foundA,foundB,ret=self.helper(root,A,B)
        if foundA and foundB:
            return ret
        
    def helper(self,node,A,B):
        if node==None:
            return False,False,None
        leftA,leftB,ret=self.helper(node.left,A,B)
        if leftA and leftB:
            return leftA,leftB,ret
        rightA,rightB,ret=self.helper(node.right,A,B)
        if rightA and rightB:
            return rightA,rightB,ret
            
        foundA = leftA or rightA
        foundB = leftB or rightB
        if foundA and foundB:
            return True,True,node
        if foundA==True:
            return True,node==B,node
        if foundB==True:
            return node==A,True,node
        return node==A, node==B, node
        
578

 

95. Validate Binary Search Tree
Description

    Given a binary tree, determine if it is a valid binary search tree (BST).

    Assume a BST is defined as follows:

        The left subtree of a node contains only nodes with keys less than the node's key.
        The right subtree of a node contains only nodes with keys greater than the node's key.
        Both the left and right subtrees must also be binary search trees.
        A single node tree is a BST

Example 1:

    Input:  {-1}
    Output:true
    Explanation:
    For the following binary tree(only one node):
              -1
    This is a binary search tree.

Example 2:

    Input:  {2,1,4,#,#,3,5}
    Output: true
    For the following binary tree:
          2
         / \
        1   4
           / \
          3   5
    This is a binary search tree.

95. Validate Binary Search Tree
Description

    Given a binary tree, determine if it is a valid binary search tree (BST).

    Assume a BST is defined as follows:

        The left subtree of a node contains only nodes with keys less than the node's key.
        The right subtree of a node contains only nodes with keys greater than the node's key.
        Both the left and right subtrees must also be binary search trees.
        A single node tree is a BST

Example 1:

    Input:  {-1}
    Output:true
    Explanation:
    For the following binary tree(only one node):
              -1
    This is a binary search tree.

Example 2:

    Input:  {2,1,4,#,#,3,5}
    Output: true
    For the following binary tree:
          2
         / \
        1   4
           / \
          3   5
    This is a binary search tree.
95

 

901. Closest Binary Search Tree Value II

Description
    Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.

        Given target value is a floating point.
        You may assume k is always valid, that is: k ≤ total nodes.
        You are guaranteed to have only one unique set of k values in the BST that are closest to the target.

Example 1:

    Input:
    {1}
    0.000000
    1
    Output:
    [1]
    Explanation:
    Binary tree {1},  denote the following structure:
     1

Example 2:

    Input:
    {3,1,4,#,2}
    0.275000
    2
    Output:
    [1,2]
    Explanation:
    Binary tree {3,1,4,#,2},  denote the following structure:
      3
     /  \
    1    4
     \
      2

Challenge
    Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?

#coding:utf-8
"""
901. Closest Binary Search Tree Value II

Description
    Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.

        Given target value is a floating point.
        You may assume k is always valid, that is: k ≤ total nodes.
        You are guaranteed to have only one unique set of k values in the BST that are closest to the target.

Example 1:

    Input:
    {1}
    0.000000
    1
    Output:
    [1]
    Explanation:
    Binary tree {1},  denote the following structure:
     1

Example 2:

    Input:
    {3,1,4,#,2}
    0.275000
    2
    Output:
    [1,2]
    Explanation:
    Binary tree {3,1,4,#,2},  denote the following structure:
      3
     /  \
    1    4
     \
      2

Challenge

    Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?
"""
#參考:https://www.jiuzhang.com/solution/closest-binary-search-tree-value-ii/#tag-highlight-lang-python
#一次中序遍歷獲得排序鏈表,順便記錄一下最接近的數,接着用雙指針從最接近的數向兩邊搜索,加入結果鏈表。

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param root: the given BST
    @param target: the given target
    @param k: the given k
    @return: k values in the BST that are closest to the target
    """
    def closestKValues(self, root, target, k):
        # write your code here
        
        ret =[]
        if root==None:
            return ret
        import sys
        self.nearest = None
        self.dif=sys.maxsize
        self.helper(root,target,ret)
        i=j=ret.index(self.nearest)
        temp=[ret[i]]
        k-=1
        while k>0 and i>0 and j<len(ret)-1:
            if abs(ret[i-1]-target)<=abs(ret[j+1]-target):
                i-=1
                temp.append(ret[i])
            else:
                j+=1
                temp.append(ret[j])
            k-=1
        if k>0:
            if i==0:
                temp.extend(ret[j+1:j+k+1])
            else:
                temp.extend(ret[i-k:i])
        return temp
        
    def helper(self,node,target,ret):
        if node==None:
            return
        if node.left:
            self.helper(node.left,target,ret)
        if abs(node.val-target)<self.dif:
            self.dif = abs(node.val-target)
            self.nearest=node.val
        ret.append(node.val)
        if node.right:
            self.helper(node.right,target,ret)
901

 

86. Binary Search Tree Iterator

description

    Design an iterator over a binary search tree with the following rules:

        Elements are visited in ascending order (i.e. an in-order traversal)
        next() and hasNext() queries run in O(1) time in average.

Example 1

    Input:  {10,1,11,#,6,#,12}
    Output:  [1, 6, 10, 11, 12]
    Explanation:
    The BST is look like this:
      10
      /\
     1 11
      \  \
       6  12
    You can return the inorder traversal of a BST [1, 6, 10, 11, 12]

Example 2

    Input: {2,1,3}
    Output: [1,2,3]
    Explanation:
    The BST is look like this:
      2
     / \
    1   3
    You can return the inorder traversal of a BST tree [1,2,3]

Challenge

    Extra memory usage O(h), h is the height of the tree.
    Super Star: Extra memory usage O(1)

#coding:utf-8
"""
86. Binary Search Tree Iterator
description

    Design an iterator over a binary search tree with the following rules:

        Elements are visited in ascending order (i.e. an in-order traversal)
        next() and hasNext() queries run in O(1) time in average.

Example 1

    Input:  {10,1,11,#,6,#,12}
    Output:  [1, 6, 10, 11, 12]
    Explanation:
    The BST is look like this:
      10
      /\
     1 11
      \  \
       6  12
    You can return the inorder traversal of a BST [1, 6, 10, 11, 12]

Example 2

    Input: {2,1,3}
    Output: [1,2,3]
    Explanation:
    The BST is look like this:
      2
     / \
    1   3
    You can return the inorder traversal of a BST tree [1,2,3]

Challenge

    Extra memory usage O(h), h is the height of the tree.
    Super Star: Extra memory usage O(1)
"""

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None

Example of iterate a tree:
iterator = BSTIterator(root)
while iterator.hasNext():
    node = iterator.next()
    do something for node 
"""


class BSTIterator:
    """
    @param: root: The root of binary tree.
    """
    def __init__(self, root):
        # do intialization if necessary
        self.ret =[]
        self.traverse(root)
        self.length=len(self.ret)
        self.k=0

    """
    @return: True if there has next node, or false
    """
    def hasNext(self, ):
        # write your code here
        if self.k<self.length:
            return True

    """
    @return: return next node
    """
    def next(self, ):
        # write your code here
        temp = self.ret[self.k]
        self.k+=1
        return temp
        
    def traverse(self,root):
        if root==None:
            return 
        if root.left:
            self.traverse(root.left)
        self.ret.append(root)
        if root.right:
            self.traverse(root.right)
86

 

詳細代碼可參見:https://github.com/silence-cho/cv-learning

相關文章
相關標籤/搜索