leetcode(75,455,69,241,160)

75.顏色分類(中等)

這題又被稱爲荷蘭國旗問題。

給定一個包含紅色、白色和藍色,一共n 個元素的數組,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。

此題中,我們使用整數 0、1 和 2 分別表示紅色、白色和藍色。

注意:

不能使用代碼庫中的排序函數來解決這道題。

示例:

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

解法一:

題目中只會出現0,1,2,其實就是要把題目中的0,1,2按照升序排好就可以了,我們可以從頭遍歷輸入的數組,碰到是0,就把數組對應位置改爲0,碰到1,就計數,遍歷完後,0就已經排好了,按照記錄的1的數目把1放到0的後面,然後把剩下位置改爲2就可以了。代碼如下:

class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        i, j = 0, 0
        for s in nums:
            if s == 0:
                nums[i] = 0
                i += 1
            elif s == 1:
                j += 1
        for s in range(i, i + j):
            nums[s] = 1
        for s in range(i + j, len(nums)):
            nums[s] = 2

解法二:

用三個指針p0,p2,curr來分別表示最右邊一個0,最左邊一個2,以及當前元素。

當curr=0時,把p0與curr的元素互換,並且兩個指針都加1,如果curr=2,則互換p2與curr,並把p2減一,但是注意curr不加一,因爲交換過來的元素還要判斷一次,如果curr=1,則curr加1即可。

class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        p0 = 0
        p2 = len(nums)-1
        curr = 0
        while curr <= p2:
            if nums[curr] == 2:
                nums[p2], nums[curr] = nums[curr], nums[p2]
                p2 -= 1
            elif nums[curr] == 0:
                nums[p0], nums[curr] = nums[curr], nums[p0]
                curr += 1
                p0 += 1
            else:
                curr += 1

455.分發餅乾(簡單)

假設你是一位很棒的家長,想要給你的孩子們一些小餅乾。但是,每個孩子最多隻能給一塊餅乾。對每個孩子 i ,都有一個胃口值gi ,這是能讓孩子們滿足胃口的餅乾的最小尺寸;並且每塊餅乾 j ,都有一個尺寸 sj。如果 sj >= gi,我們可以將這個餅乾 j 分配給孩子 i ,這個孩子會得到滿足。你的目標是儘可能滿足越多數量的孩子,並輸出這個最大數值。

注意:

你可以假設胃口值爲正。
一個小朋友最多隻能擁有一塊餅乾。

示例1:

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

輸出: 1

解釋: 
你有三個孩子和兩塊小餅乾,3個孩子的胃口值分別是:1,2,3。
雖然你有兩塊小餅乾,由於他們的尺寸都是1,你只能讓胃口值是1的孩子滿足。
所以你應該輸出1。

示例2:

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

輸出: 2

解釋: 
你有兩個孩子和三塊小餅乾,2個孩子的胃口值分別是1,2。
你擁有的餅乾數量和尺寸都足以讓所有孩子滿足。
所以你應該輸出2.

解法一:

首先把兩個list進行升序排列,之後從第一個孩子和第一塊餅乾開始判斷,如果g[i]>s[j],說明不能滿足孩子的胃口,j+1,否則j,i,count都加一,循環條件是某一個列表遍歷完。這裏注意的是循環條件其實可以是兩個一起制定的,用and連接就好,方便很多。

class Solution(object):
    def findContentChildren(self, g, s):
        """
        :type g: List[int]
        :type s: List[int]
        :rtype: int
        """
        g.sort()
        s.sort()
        i = 0
        j = 0
        count = 0
        while i < len(g) and j < len(s):
            if g[i] > s[j]:
                j += 1
            else:
                count += 1
                i += 1
                j += 1
        return count

解法二:

可以改的更加優雅一些,觀察上面的代碼,可以發現無論什麼操作j都要加一,且i和count都是同步的,所以可以這樣精簡。

class Solution(object):
    def findContentChildren(self, g, s):
        """
        :type g: List[int]
        :type s: List[int]
        :rtype: int
        """
        g.sort()
        s.sort()
        i = 0
        j = 0
        while i < len(g) and j < len(s):
            if g[i] <= s[j]:
                i += 1
            j += 1
        return i

69.x的平方根 (簡單)

實現 int sqrt(int x) 函數。

計算並返回 x 的平方根,其中 x 是非負整數。

由於返回類型是整數,結果只保留整數的部分,小數部分將被捨去。

示例1:

輸入: 4
輸出: 2

示例2:

輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842..., 
     由於返回類型是整數,小數部分將被捨去。

解法一:

使用二分法,但是二分法的邊界問題很噁心,一不小心就進入了死循環

class Solution(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        left = 0
        right = x // 2 + 1  #爲了照顧輸入1
        while left<right:
            mid = (left+right) // 2 + 1  
            square = mid*mid
            if square == x:
                return mid
            elif square>x:
                right = mid-1
            else:
                left = mid
        return left
            

解法二:

用牛頓迭代法,求a的平方根,相當於求

f(x) = x^2 -a

當f(x)=0時的根

image
這個函數的導函數是2x,也就是我猜的每一個x等於x-f(x)/2x,把f(x)=x^2-a帶進去,可以得到迭代公式x = 1/2(x+a/x),進行迭代就可以,終止迭代的條件是前後兩次的x值相差小於1*10^-6,即返回x。

class Solution(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        cur = x #這個數隨便寫,多少都行
        while True:
            pre = cur
            cur = (cur + x/cur) / 2
            if abs(cur-pre)<1e-6:
                return int(cur)

241.爲運算表達式設計優先級(中等)

給定一個含有數字和運算符的字符串,爲表達式添加括號,改變其運算優先級以求出不同的結果。你需要給出所有可能的組合的結果。有效的運算符號包含 +, - 以及 * 。

示例1:

輸入: "2-1-1"
輸出: [0, 2]
解釋: 
((2-1)-1) = 0 
(2-(1-1)) = 2

示例2:

輸入: "2*3-4*5"
輸出: [-34, -14, -10, -10, 10]
解釋: 
(2*(3-(4*5))) = -34 
((2*3)-(4*5)) = -14 
((2*(3-4))*5) = -10 
(2*((3-4)*5)) = -10 
(((2*3)-4)*5) = 10

解法一:

採用分治+遞歸的思想,把字符串按照運算符號分爲左邊和右邊,一直分到只剩單獨一個數字時,根據輸入的符號進行運算,簡單的說就是,函數返回的就是目前輸入的字符串的所有的運算結果可能。

class Solution(object):
    def diffWaysToCompute(self, input):
        """
        :type input: str
        :rtype: List[int]
        """
        if input.isdigit():
            return [int(input)]
        res = []
        for i in range(len(input)):
            if input[i] in "+-*":
                res1 = self.diffWaysToCompute(input[:i])
                res2 = self.diffWaysToCompute(input[i+1:])
                for l in res1:
                    for r in res2:
                        res.append(self.helper(l, r, input[i]))
        return res
    def helper(self, a, b, op):
        if op == "+":
            return a+b
        elif op == "-":
            return a-b
        else:
            return a*b
            
    #helper函數也可以這麼寫:
    """
        def helper(self, a, b, op):
            return {
                    '+': a + b,
                    '-': a - b,
                    '*': a * b
                }[op]
    """

160.相交鏈表(中等)

編寫一個程序,找到兩個單鏈表相交的起始節點。

如下面的兩個鏈表:
image
在節點 c1 開始相交。

示例1:

image

輸入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
輸出:Reference of the node with value = 8
輸入解釋:相交節點的值爲 8 (注意,如果兩個列表相交則不能爲 0)。從各自的表頭開始算起,鏈表 A 爲 [4,1,8,4,5],鏈表 B 爲 [5,0,1,8,4,5]。在 A 中,相交節點前有 2 個節點;在 B 中,相交節點前有 3 個節點。

示例2:

image

輸入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
輸出:Reference of the node with value = 2
輸入解釋:相交節點的值爲 2 (注意,如果兩個列表相交則不能爲 0)。從各自的表頭開始算起,鏈表 A 爲 [0,9,1,2,4],鏈表 B 爲 [3,2,4]。在 A 中,相交節點前有 3 個節點;在 B 中,相交節點前有 1 個節點。

示例3:

image

輸入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
輸出:null
輸入解釋:從各自的表頭開始算起,鏈表 A 爲 [2,6,4],鏈表 B 爲 [1,5]。由於這兩個鏈表不相交,所以 intersectVal 必須爲 0,而 skipA 和 skipB 可以是任意值。
解釋:這兩個鏈表不相交,因此返回 null。

解法一:

首先計算出兩個鏈表的長度差,把長的那一條的指針往後移動差值步,之後兩個鏈表一起向後遍歷,當遇到一樣的值時就是相交的節點。

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

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        a = headA
        b = headB
        len_a = 0
        len_b = 0
        while a:
            a = a.next
            len_a += 1
        while b:
            b = b.next
            len_b += 1
        if a != b:
            return None
        a = headA
        b = headB
        if len_a > len_b:
            for _ in range(len_a-len_b):
                a = a.next
        elif len_b > len_a:
            for _ in range(len_b - len_a):
                b = b.next
        while a!=b:
            a = a.next
            b = b.next
        return a

解法二:

其實還是消除長度差,不過我們可以把兩個鏈表拼在一起,一個長-短,一個短-長,當兩個指針相同時即達成條件,如下圖所示:
image

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

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        a = headA
        b = headB
        while a!=b:
            a = a.next if a else headB
            b = b.next if b else headA
        return a
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章