LeetCode 中等題解(1)

16 最接近的三數之和

Question

給定一個包括 n 個整數的數組 nums 和 一個目標值 target。找出 nums 中的三個整數,使得它們的和與 target 最接近。返回這三個數的和。假定每組輸入只存在唯一答案。

例如,給定數組 nums = [-1,2,1,-4], 和 target = 1.

與 target 最接近的三個數的和爲 2. (-1 + 2 + 1 = 2).

Answer

#
# @lc app=leetcode.cn id=16 lang=python3
#
# [16] 最接近的三數之和
#


# @lc code=start
class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        n = len(nums)
        if (not nums or n < 3):
            return None
        nums.sort()
        res = float("inf")
        for i in range(n):
            if (i > 0 and nums[i] == nums[i - 1]):
                continue
            L = i + 1
            R = n - 1
            while (L < R):
                cur_sum = nums[i] + nums[L] + nums[R]

                if (cur_sum == target):
                    return target
                if (abs(cur_sum - target) < abs(res - target)):
                    res = cur_sum
                if (cur_sum - target < 0):
                    L += 1
                else:
                    R -= 1
        return res


# @lc code=end


17 電話號碼的字母組合

Question

給定一個僅包含數字 2-9 的字符串,返回所有它能表示的字母組合。

給出數字到字母的映射如下(與電話按鍵相同)。注意 1 不對應任何字母。

img

示例:

輸入:"23"
輸出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

說明:
儘管上面的答案是按字典序排列的,但是你可以任意選擇答案輸出的順序。

Answer

#
# @lc app=leetcode.cn id=17 lang=python3
#
# [17] 電話號碼的字母組合
#

# @lc code=start
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        d_dict={
            '2': ['a', 'b', 'c'],
            '3': ['d', 'e', 'f'],
            '4': ['g', 'h', 'i'],
            '5': ['j', 'k', 'l'],
            '6': ['m', 'n', 'o'],
            '7': ['p', 'q', 'r', 's'],
            '8': ['t', 'u', 'v'],
            '9': ['w', 'x', 'y', 'z']
        }
        ans_a = []
        ans_b = []
        for d in digits:
            if ans_a == []:      
                for s in d_dict[d]:
                    ans_a.append(s)
            else:
                for s in d_dict[d]:
                    for i in range(len(ans_a)):
                        ans_b.append(ans_a[i] + s)
            if ans_b != []:
                ans_a = ans_b
                ans_b = []
        return ans_a


# @lc code=end


18 四數之和

Question

給定一個包含 n 個整數的數組 nums 和一個目標值 target,判斷 nums 中是否存在四個元素 a,**b,cd ,使得 a + b + c + d 的值與 target 相等?找出所有滿足條件且不重複的四元組。

注意:

答案中不可以包含重複的四元組。

示例:

給定數組 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

滿足要求的四元組集合爲:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

Answer

#
# @lc app=leetcode.cn id=18 lang=python3
#
# [18] 四數之和
#


# @lc code=start
class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        if not nums or len(nums) < 4:
            return []
        nums.sort()
        res = []
        for a in range(len(nums) - 3):
            if a > 0 and nums[a] == nums[a - 1]:
                continue
            for b in range(a + 1, len(nums) - 2):
                if b > a + 1 and nums[b] == nums[b - 1]:
                    continue
                c = b + 1
                d = len(nums) - 1
                while c < d:
                    sum = nums[a] + nums[b] + nums[c] + nums[d]
                    if sum == target:
                        res.append([nums[a], nums[b], nums[c], nums[d]])
                        while c < d and nums[c] == nums[c + 1]:
                            c += 1
                        while c < d and nums[d] == nums[d - 1]:
                            d -= 1
                        c += 1
                        d -= 1
                    elif sum < target:
                        c += 1
                    else:
                        d -= 1
        return res


# @lc code=end

19 刪除鏈表的倒數第N個節點

Question

給定一個鏈表,刪除鏈表的倒數第 n 個節點,並且返回鏈表的頭結點。

示例:

給定一個鏈表: 1->2->3->4->5, 和 n = 2.

當刪除了倒數第二個節點後,鏈表變爲 1->2->3->5.

說明:

給定的 n 保證是有效的。

進階:

你能嘗試使用一趟掃描實現嗎?

Answer

#
# @lc app=leetcode.cn id=19 lang=python3
#
# [19] 刪除鏈表的倒數第N個節點
#

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


class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        node_no = 0
        node = head
        while node is not None:
            node = node.next
            node_no += 1
        node_no -= n + 1
        node = head
        if node_no == -1:
            head = head.next
        else:
            while(node_no):
                node = node.next
                node_no -= 1
            node.next = node.next.next
        return head


# @lc code=end

PS: 兩邊掃描,第一遍拿到刪除點位置,第二遍找到刪除點進行刪除。

22 括號生成

Question

給出 n 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。

例如,給出 n = 3,生成結果爲:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

Answer

#
# @lc app=leetcode.cn id=22 lang=python3
#
# [22] 括號生成
#


# @lc code=start
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        dp = [[] for _ in range(n + 1)]
        dp[0] = [""]
        for i in range(1, n + 1):
            for p in range(i):
                l1 = dp[p]
                l2 = dp[i - 1 - p]
                for k1 in l1:
                    for k2 in l2:
                        dp[i].append("({0}){1}".format(k1, k2))

        return dp[n]


# @lc code=end

PS:動態規劃的理解方法,可以參考這篇題解

24 兩兩交換鏈表中的節點

Question

給定一個鏈表,兩兩交換其中相鄰的節點,並返回交換後的鏈表。

你不能只是單純的改變節點內部的值,而是需要實際的進行節點交換。

示例:

給定 1->2->3->4, 你應該返回 2->1->4->3.

Answer

#
# @lc app=leetcode.cn id=24 lang=python3
#
# [24] 兩兩交換鏈表中的節點
#

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


class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head
        node_id = 0
        head_pre = head
        big_node = None
        ans = head.next
        while (head.next):
            head = head.next
            node_id += 1
            if node_id % 2 == 1:
                head_pre.next = head.next
                if big_node is not None:
                    big_node.next = head
                head.next = head_pre        
                head = head.next
                big_node = head
            head_pre = head
        return ans


# @lc code=end

PS:注意只有零個節點或者一個節點的極端情況。

29 兩數相除

Question

給定兩個整數,被除數 dividend 和除數 divisor。將兩數相除,要求不使用乘法、除法和 mod 運算符。

返回被除數 dividend 除以除數 divisor 得到的商。

示例 1:

輸入: dividend = 10, divisor = 3
輸出: 3

示例 2:

輸入: dividend = 7, divisor = -3
輸出: -2

說明:

  • 被除數和除數均爲 32 位有符號整數。
  • 除數不爲 0。
  • 假設我們的環境只能存儲 32 位有符號整數,其數值範圍是 [−231, 231 − 1]。本題中,如果除法結果溢出,則返回 231 − 1。

Answer

#
# @lc app=leetcode.cn id=29 lang=python3
#
# [29] 兩數相除
#

# @lc code=start
class Solution:
    def divide(self, dividend: int, divisor: int) -> int:
        i, a, b = 0, abs(dividend), abs(divisor)
        if a == 0 or a < b:
            return 0
        while b <= a:
            b = b << 1
            i = i + 1
        else:
            res = (1 << (i - 1)) + self.divide(a - (b >> 1), abs(divisor))
            if (dividend ^ divisor) < 0:
                res = -res
            return min(res, (1 << 31) - 1)
# @lc code=end


PS:來自評論區算法,實在是太強了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章