1. 程式人生 > 其它 >LeetCode部分題解(一)

LeetCode部分題解(一)

技術標籤:LeetCode

LeetCode部分題解(一)

一、前言

因為這周選的題單太難把我這個蒟蒻打崩了╮(╯﹏╰)╭這周我帶來了一些LeetCode的題解,因為剛開始寫,也是第一次嘗試Python寫,所以選的題難度也不大。也是防止打牛客小白賽再在簡單題翻車┭┮﹏┭┮

二、go go go

1、1689. 十-二進位制數的最少數目

如果一個十進位制數字不含任何前導零,且每一位上的數字不是 0 就是 1 ,那麼該數字就是一個 十-二進位制數 。例如,101 和 1100 都是 十-二進位制數,而 112 和 3001 不是。

給你一個表示十進位制整數的字串 n ,返回和為 n 的 十-二進位制數 的最少數目。

示例 1:

輸入:n = “32”
輸出:3
解釋:10 + 11 + 11 = 32
示例 2:

輸入:n = “82734”
輸出:8
示例 3:

輸入:n = “27346209830709182346”
輸出:9

提示:

1 <= n.length <= 105
n 僅由數字組成
n 不含任何前導零並總是表示正整數

這道題真的簡單,給了三個樣例,所以直接秒解,顯然是每位數中最大的那個,Python更是一行秒。

AC code

class Solution:
    def minPartitions(self, n: str) -> int:
        return int
(max(n))

1476. 子矩形查詢

請你實現一個類 SubrectangleQueries ,它的建構函式的引數是一個 rows x cols 的矩形(這裡用整數矩陣表示),並支援以下兩種操作:

1.updateSubrectangle(int row1, int col1, int row2, int col2, int newValue)

  • newValue 更新以 (row1,col1) 為左上角且以 (row2,col2) 為右下角的子矩形。

2.getValue(int row, int col)

  • 返回矩形中座標 (row,col) 的當前值。

示例 1:

輸入:
["SubrectangleQueries","getValue","updateSubrectangle","getValue","getValue","updateSubrectangle","getValue","getValue"]
[[[[1,2,1],[4,3,4],[3,2,1],[1,1,1]]],[0,2],[0,0,3,2,5],[0,2],[3,1],[3,0,3,2,10],[3,1],[0,2]]
輸出:
[null,1,null,5,5,null,10,5]
解釋:
SubrectangleQueries subrectangleQueries = new SubrectangleQueries([[1,2,1],[4,3,4],[3,2,1],[1,1,1]]);  
// 初始的 (4x3) 矩形如下:
// 1 2 1
// 4 3 4
// 3 2 1
// 1 1 1
subrectangleQueries.getValue(0, 2); // 返回 1
subrectangleQueries.updateSubrectangle(0, 0, 3, 2, 5);
// 此次更新後矩形變為:
// 5 5 5
// 5 5 5
// 5 5 5
// 5 5 5 
subrectangleQueries.getValue(0, 2); // 返回 5
subrectangleQueries.getValue(3, 1); // 返回 5
subrectangleQueries.updateSubrectangle(3, 0, 3, 2, 10);
// 此次更新後矩形變為:
// 5   5   5
// 5   5   5
// 5   5   5
// 10  10  10 
subrectangleQueries.getValue(3, 1); // 返回 10
subrectangleQueries.getValue(0, 2); // 返回 5

示例 2:

輸入:
["SubrectangleQueries","getValue","updateSubrectangle","getValue","getValue","updateSubrectangle","getValue"]
[[[[1,1,1],[2,2,2],[3,3,3]]],[0,0],[0,0,2,2,100],[0,0],[2,2],[1,1,2,2,20],[2,2]]
輸出:
[null,1,null,100,100,null,20]
解釋:
SubrectangleQueries subrectangleQueries = new SubrectangleQueries([[1,1,1],[2,2,2],[3,3,3]]);
subrectangleQueries.getValue(0, 0); // 返回 1
subrectangleQueries.updateSubrectangle(0, 0, 2, 2, 100);
subrectangleQueries.getValue(0, 0); // 返回 100
subrectangleQueries.getValue(2, 2); // 返回 100
subrectangleQueries.updateSubrectangle(1, 1, 2, 2, 20);
subrectangleQueries.getValue(2, 2); // 返回 20

提示:

  • 最多有 500updateSubrectanglegetValue 操作。
  • 1 <= rows, cols <= 100
  • rows == rectangle.length
  • cols == rectangle[i].length
  • 0 <= row1 <= row2 < rows
  • 0 <= col1 <= col2 < cols
  • 1 <= newValue, rectangle[i][j] <= 10^9
  • 0 <= row < rows
  • 0 <= col < cols

這道題要求我們實現兩個功能,一個是更新矩陣的值,一個是輸出。其實可以理解為一個二維陣列,改變其中一個小子陣列的值,然後輸出一個點,也不難。

class SubrectangleQueries:
    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1,row2+1):
            for j in range(col1,col2+1):
                 self.rectangle[i][j] = newValue
    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]

1480. 一維陣列的動態和

給你一個數組 nums 。陣列「動態和」的計算公式為:runningSum[i] = sum(nums[0]…nums[i]) 。

請返回 nums 的動態和。

示例 1:

輸入:nums = [1,2,3,4]
輸出:[1,3,6,10]
解釋:動態和計算過程為 [1, 1+2, 1+2+3, 1+2+3+4] 。
示例 2:

輸入:nums = [1,1,1,1,1]
輸出:[1,2,3,4,5]
解釋:動態和計算過程為 [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1] 。
示例 3:

輸入:nums = [3,1,2,10,1]
輸出:[3,4,6,16,17]

提示:

1 <= nums.length <= 1000
-10^6 <= nums[i] <= 10^6

這道題唯一要注意就是不要一個一個算,直接線性的,用遞推解決,難度也不大

AC code

class Solution:
    def runningSum(self, nums: List[int]) -> List[int]:
        k = len(nums)
        i = 1
        ans = []
        ans.append(nums[0])
        while i < k:
             ans.append(nums[i] + ans[i-1])
             i = i + 1
        return ans

1672. 最富有客戶的資產總量

給你一個 m x n 的整數網格 accounts ,其中 accounts[i][j] 是第 i 位客戶在第 j 家銀行託管的資產數量。返回最富有客戶所擁有的 資產總量 。

客戶的 資產總量 就是他們在各家銀行託管的資產數量之和。最富有客戶就是 資產總量 最大的客戶。

示例 1:

輸入:accounts = [[1,2,3],[3,2,1]]
輸出:6
解釋:
第 1 位客戶的資產總量 = 1 + 2 + 3 = 6
第 2 位客戶的資產總量 = 3 + 2 + 1 = 6
兩位客戶都是最富有的,資產總量都是 6 ,所以返回 6 。
示例 2:

輸入:accounts = [[1,5],[7,3],[3,5]]
輸出:10
解釋:
第 1 位客戶的資產總量 = 6
第 2 位客戶的資產總量 = 10
第 3 位客戶的資產總量 = 8
第 2 位客戶是最富有的,資產總量是 10
示例 3:

輸入:accounts = [[2,8,7],[7,1,3],[1,9,5]]
輸出:17

提示:

m == accounts.length
n == accounts[i].length
1 <= m, n <= 50
1 <= accounts[i][j] <= 100

這道題資料量比較小,所以就是簡單的加起來就行

AC code

class Solution:
    def maximumWealth(self, accounts: List[List[int]]) -> int:
        ans = 0
        for i in range(len(accounts)):
            k = 0
            for j in range(len(accounts[i])):
                k += accounts[i][j]
            if k > ans :
                ans = k
        return ans

劍指 Offer 64. 求1+2+…+n

求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。

示例 1:

輸入: n = 3
輸出: 6
示例 2:

輸入: n = 9
輸出: 45

限制:

1 <= n <= 10000

這道題還是比較有意思的,大家可以先思考一下


其實如果我們按照迴圈來思考的話,不能迴圈就只能選擇遞迴了,所以大概方向就是遞迴,問題是怎麼控制邊界?這也是比較難想的地方。然後我們先看看能用的工具,一看到那麼多關鍵字不能用,其實我們也就剩那些邏輯運算子和位運算子了。邏輯運算的話我們可以利用and的特性來做一個短路,也是我的解法。LeetCode官方題解也提供了另一種很好的思路。其實我看到這道題第一反應是把他用求和公式處理一下,變成一次乘法一次除法,然後用位運算解決。但我位運算太爛了O__O "…翻了半天資料也沒想明白。然後LeetCode給的解法是把每位單獨相乘(因為位數有限,資料不大,可以不用 迴圈,直接暴力)具體操作是如果b在某位上為1,則答案加上a在該位的值,挺巧妙的。

AC code

class Solution:
    def sumNums(self, n: int) -> int:
        return n and n + self.sumNums(n-1)

面試題 02.03. 刪除中間節點

實現一種演算法,刪除單向連結串列中間的某個節點(即不是第一個或最後一個節點),假定你只能訪問該節點。

示例:

輸入:單向連結串列a->b->c->d->e->f中的節點c
結果:不返回任何資料,但該連結串列變為a->b->d->e->f

這就是連結串列的操作,我們只能訪問當前的結點,而我們一般考慮的刪除應該是知道一個節點的上一個節點,將他指向刪除結點的下一個結點從而完成刪除,現在只能訪問刪除結點,所以我們將刪除節點賦值為刪除節點的下一個結點,然後刪除下一個結點

AC code

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

class Solution:
    def deleteNode(self, node):
        node.val = node.next.val
        node.next = node.next.next
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        

劍指 Offer 58 - II. 左旋轉字串

字串的左旋轉操作是把字串前面的若干個字元轉移到字串的尾部。請定義一個函式實現字串左旋轉操作的功能。比如,輸入字串"abcdefg"和數字2,該函式將返回左旋轉兩位得到的結果"cdefgab"。

示例 1:

輸入: s = “abcdefg”, k = 2
輸出: “cdefgab”
示例 2:

輸入: s = “lrloseumgh”, k = 6
輸出: “umghlrlose”

限制:

1 <= k < s.length <= 10000

是非常簡單的字串操作,但用Python寫出來,和之前比較熟悉的c++相比,又精簡了許多

AC code

class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        return s[n:] + s[:n]

1512. 好數對的數目

給你一個整數陣列 nums 。

如果一組數字 (i,j) 滿足 nums[i] == nums[j] 且 i < j ,就可以認為這是一組 好數對 。

返回好數對的數目。

示例 1:

輸入:nums = [1,2,3,1,1,3]
輸出:4
解釋:有 4 組好數對,分別是 (0,3), (0,4), (3,4), (2,5) ,下標從 0 開始
示例 2:

輸入:nums = [1,1,1,1]
輸出:6
解釋:陣列中的每組數字都是好數對
示例 3:

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

提示:

1 <= nums.length <= 100
1 <= nums[i] <= 100

這個題要先找規律,會發現有幾個好數對取決於有幾個相同的數字,對與每個新數字,前面每個相同的數字都可以增加一個新的好數對,所以就是等差數列求和。

AC code

class Solution:
    def numIdenticalPairs(self, nums: List[int]) -> int:
        book = [0 for i in range(109)]
        ans = 0
        for i in range(len(nums)):
            book[nums[i]] += 1
        for i in range(109):
            ans += (book[i] * (book[i] - 1)) / 2
        return int(ans)

771. 寶石與石頭

給定字串J 代表石頭中寶石的型別,和字串 S代表你擁有的石頭。 S 中每個字元代表了一種你擁有的石頭的型別,你想知道你擁有的石頭中有多少是寶石。

J 中的字母不重複,J 和 S中的所有字元都是字母。字母區分大小寫,因此"a"和"A"是不同型別的石頭。

示例 1:

輸入: J = “aA”, S = “aAAbbbb”
輸出: 3
示例 2:

輸入: J = “z”, S = “ZZ”
輸出: 0
注意:

S 和 J 最多含有50個字母。
J 中的字元不重複。

這道題還是字串統計,難度不大,這裡我發現用book陣列在時間上優勢挺大的,這兩道題都擊敗了超過93%的使用者ヾ(o◕∀◕)ノヾ

AC code

class Solution:
    def numJewelsInStones(self, jewels: str, stones: str) -> int:
        ans = 0
        book = [0 for i in range(200)]
        for i in range(len(stones)):
            book[ord(stones[i])] += 1
        for i in range(len(jewels)):
            ans += book[ord(jewels[i])]
        return ans

1431. 擁有最多糖果的孩子

給你一個數組 candies 和一個整數 extraCandies ,其中 candies[i] 代表第 i 個孩子擁有的糖果數目。

對每一個孩子,檢查是否存在一種方案,將額外的 extraCandies 個糖果分配給孩子們之後,此孩子有 最多 的糖果。注意,允許有多個孩子同時擁有 最多 的糖果數目。

示例 1:

輸入:candies = [2,3,5,1,3], extraCandies = 3
輸出:[true,true,true,false,true]
解釋:
孩子 1 有 2 個糖果,如果他得到所有額外的糖果(3個),那麼他總共有 5 個糖果,他將成為擁有最多糖果的孩子。
孩子 2 有 3 個糖果,如果他得到至少 2 個額外糖果,那麼他將成為擁有最多糖果的孩子。
孩子 3 有 5 個糖果,他已經是擁有最多糖果的孩子。
孩子 4 有 1 個糖果,即使他得到所有額外的糖果,他也只有 4 個糖果,無法成為擁有糖果最多的孩子。
孩子 5 有 3 個糖果,如果他得到至少 2 個額外糖果,那麼他將成為擁有最多糖果的孩子。
示例 2:

輸入:candies = [4,2,1,1,2], extraCandies = 1
輸出:[true,false,false,false,false]
解釋:只有 1 個額外糖果,所以不管額外糖果給誰,只有孩子 1 可以成為擁有糖果最多的孩子。
示例 3:

輸入:candies = [12,1,12], extraCandies = 10
輸出:[true,false,true]

提示:

2 <= candies.length <= 100
1 <= candies[i] <= 100
1 <= extraCandies <= 50

大家可能已經發現我選的題目有多水了w(゚Д゚)w直接上程式碼了

AC code

class Solution:
    def kidsWithCandies(self, candies: List[int], extraCandies: int) -> List[bool]:
        m = max(candies)
        ans = [True for i in range(len(candies))]
        for i in range(len(candies)):
            if candies[i] + extraCandies < m:
                ans[i] = False
        return ans

1470. 重新排列陣列

給你一個數組 nums ,陣列中有 2n 個元素,按 [x1,x2,…,xn,y1,y2,…,yn] 的格式排列。

請你將陣列按 [x1,y1,x2,y2,…,xn,yn] 格式重新排列,返回重排後的陣列。

示例 1:

輸入:nums = [2,5,1,3,4,7], n = 3
輸出:[2,3,5,4,1,7]
解釋:由於 x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 ,所以答案為 [2,3,5,4,1,7]
示例 2:

輸入:nums = [1,2,3,4,4,3,2,1], n = 4
輸出:[1,4,2,3,3,2,4,1]
示例 3:

輸入:nums = [1,1,2,2], n = 2
輸出:[1,2,1,2]

提示:

1 <= n <= 500
nums.length == 2n
1 <= nums[i] <= 10^3

一個迴圈,把之前的數列分成兩個來取就好了,注意找規律即可

AC code

class Solution:
    def shuffle(self, nums: List[int], n: int) -> List[int]:
        ans = [0 for i in range(2*n)]
        for i in range(n):
            ans [2*i] = nums[i]
            ans [2*i+1] = nums[i+n]
        return ans

1486. 陣列異或操作

給你兩個整數,n 和 start 。

陣列 nums 定義為:nums[i] = start + 2*i(下標從 0 開始)且 n == nums.length 。

請返回 nums 中所有元素按位異或(XOR)後得到的結果。

示例 1:

輸入:n = 5, start = 0
輸出:8
解釋:陣列 nums 為 [0, 2, 4, 6, 8],其中 (0 ^ 2 ^ 4 ^ 6 ^ 8) = 8 。
“^” 為按位異或 XOR 運算子。
示例 2:

輸入:n = 4, start = 3
輸出:8
解釋:陣列 nums 為 [3, 5, 7, 9],其中 (3 ^ 5 ^ 7 ^ 9) = 8.
示例 3:

輸入:n = 1, start = 7
輸出:7
示例 4:

輸入:n = 10, start = 5
輸出:2

提示:

1 <= n <= 1000
0 <= start <= 1000
n == nums.length

因為資料量不大,我們直接模擬即可

AC code

class Solution:
    def xorOperation(self, n: int, start: int) -> int:
        nums = [start + 2 * i for i in range(n)]
        ans = 0
        for i in range(n):
            ans = ans ^ nums[i]
        return ans

LCP 01. 猜數字

小A 和 小B 在玩猜數字。小B 每次從 1, 2, 3 中隨機選擇一個,小A 每次也從 1, 2, 3 中選擇一個猜。他們一共進行三次這個遊戲,請返回 小A 猜對了幾次?

輸入的guess陣列為 小A 每次的猜測,answer陣列為 小B 每次的選擇。guess和answer的長度都等於3。

示例 1:

輸入:guess = [1,2,3], answer = [1,2,3]
輸出:3
解釋:小A 每次都猜對了。
示例 2:

輸入:guess = [2,2,3], answer = [3,2,1]
輸出:1
解釋:小A 只猜對了第二次。

限制:

guess 的長度 = 3
answer 的長度 = 3
guess 的元素取值為 {1, 2, 3} 之一。
answer 的元素取值為 {1, 2, 3} 之一。

數列對比,開個迴圈,挨個比就行了,輸出相同的個數

AC code

class Solution:
    def game(self, guess: List[int], answer: List[int]) -> int:
        res = 0
        for i in range(len(guess)):
            if guess[i] == answer[i]:
                res += 1
        return res

1720. 解碼異或後的陣列

未知 整數陣列 arr 由 n 個非負整陣列成。

經編碼後變為長度為 n - 1 的另一個整數陣列 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 經編碼後得到 encoded = [1,2,3] 。

給你編碼後的陣列 encoded 和原陣列 arr 的第一個元素 first(arr[0])。

請解碼返回原陣列 arr 。可以證明答案存在並且是唯一的。

示例 1:

輸入:encoded = [1,2,3], first = 1
輸出:[1,0,2,1]
解釋:若 arr = [1,0,2,1] ,那麼 first = 1 且 encoded = [1 XOR 0, 0 XOR 2, 2 XOR 1] = [1,2,3]
示例 2:

輸入:encoded = [6,2,7,3], first = 4
輸出:[4,2,0,7,4]

提示:

2 <= n <= 10^4
encoded.length == n - 1
0 <= encoded[i] <= 10^5
0 <= first <= 10^5

這道題終於需要思考一下啦ヾ(Ő∀Ő๑)ノ但位運算大佬們肯定知道對一個數異或兩次就可以得到這個數本身(因為異或同假異真的特性)所以只需要讓frist和encoded陣列一個一個異或就可以逐漸得到整個陣列啦

AC code

class Solution:
    def decode(self, encoded: List[int], first: int) -> List[int]:
        ans = [0 for i in range(len(encoded)+1)]
        ans[0] = first
        for i in range(len(encoded)):
            ans[i+1] = ans[i] ^ encoded[i]
        return ans

面試題 16.01. 交換數字

編寫一個函式,不用臨時變數,直接交換numbers = [a, b]中a與b的值。

示例:

輸入: numbers = [1,2]
輸出: [2,1]
提示:

numbers.length == 2

這道題有意思哦,當然只要給一些很奇怪的限制我們就可以往位運算上想○( ^皿^)っHiahiahia…大家可以先思考一下


其實只要異或三次即可,再次展現了位運算的強大

AC code

class Solution:
    def swapNumbers(self, numbers: List[int]) -> List[int]:
        numbers[0] = numbers[0] ^ numbers[1]
        numbers[1] = numbers[0] ^ numbers[1]
        numbers[0] = numbers[0] ^ numbers[1] 
        return numbers

三、小結

這周題解裡面有些位運算的題還是挺有意思的。好叭這周確實有些水┭┮﹏┭┮因為LeetCode打算儘量刷完,所以會從簡單題開始慢慢加難度,然後希望Python技術也隨著這個過程逐漸提高,所以一開始的題稍微簡單了一些哈。下週我會寫一些比較厲害的東西(先立flag防鴿o(〃‘▽’〃)o