LeetCode刷題記錄(easy難度1-20題)

leetcode刷題記錄
本文記錄一下leetcode刷題記錄,記錄一下自己的解法和心得。

LeetCode

Two Sum

題目:two sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.

例子:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

題意分析:
找出數組numbers中的兩個數,它們的和為給定的一個數target,并返回這兩個數的索引(不需要去重)

思路分析

題目要求說白了就是找出這個給的數組中有哪兩個數相加等于目標結果

方法一

很容易想到我們可以遍歷兩次數組,在內循環中判斷兩次循環中的數相加是否等于target

class Solution:
    def twoSum(self, nums, target):
        length = len(nums)  # 計算輸入的列表長度
        for i in range(length):
            for j in range(length):
                if nums[i] + nums[j] == target:
                    return [i, j]

這是一種很簡單很容易能想到的方法,但此方法的時間復雜度是O(N^2),在leetcode會超時,所以不行,想要通過,肯定要降低時間復雜度

為了降低時間復雜度,我們可以犧牲空間來換取時間,使用一次循環,將時間復雜度降為O(N),所以我們可以有以下解法

方法二

可以使用字段存儲遍歷過的num和它的下標放置一個字典中,在循環這個列表,用目標結果target減正在循環的這個數,并判斷結果是否在字典中(即是否循已經遍歷過),如果結果存在如字典中,即找到相加等于結果的兩個值,如果不存在,即把值和對應下標存入字典中

class Solution:
    def twoSum(self, nums, target):
        arr = {}  # 使用字典存儲遍歷過的num和對應下標{num:index}
        length = len(nums)  # 計算輸入的列表長度
        for i in range(length):
            if (target - nums[i]) in arr:
                # 如果target-當前num的差在arr中,則表示已經找到答案,返回結果即可
                return [arr[target - nums[i]], i]
            # 否則,將該num及其下標存入arr中
            arr[nums[i]] = i

此時就犧牲了一個字典的空間,來換取了O(N)的復雜度,在leetcode也能通過

Reverse Integer

題目:Reverse Integer

Reverse digits of an integer.

例子:

Example1: x = 123, return 321
Example2: x = -123, return -321

注:The input is assumed to be a 32-bit signed integer. Your function should return 0 when the reversed integer overflows.

題意分析:
題目很簡單,將數字倒置而已,最后結果要求判斷是否為32位有符號整數

思路分析

想要倒置,又由于是int類型,我們可以使用除10求余的方式,循環求余,在每一步求出的余數放到一個數組李存起來,最后在將數組拼起來成為一個int類型整數。

但是,以上方法想想就很復雜,操作起來也很麻煩,想到基本每種語言都帶有字符串倒置的方法,我們可以先將數字轉換為字符串,在調用內置方法倒置字符串。如果是傳入的x是負數,在將其轉為為負數即可

所以我們可以有以下解法

方法一

class Solution:
    def reverse(self, x):
        # 對x判斷為正還是為負
        if x < 0:
            x = abs(x)
            # 先將數字轉為字符串,再用反向切片操作(其他語言也都有字符串倒置函數)
            return self.isOverFlows(-int(str(x)[::-1]))
        else:
            return self.isOverFlows(int(str(x)[::-1]))

    # 判斷x是否在32位有符號數
    def isOverFlows(self, x):
        if pow(-2, 31) < x < pow(2, 31):
            return x
        return 0

使用了內置的字符串高效反向切片方法,并且將判斷結果是否是屬于32位有符號數分離出一個方法,減少耦合

Palindrome Number

題目:Palindrome Number

Determine whether an integer is a palindrome. Do this without extra space.

題意分析:
判斷一個整形是否是回文,不能使用額外空間

思路分析

判斷回文,首先需要知道回文的定義,就是正向和反向都一樣的數字,也就是說這個數字需要前后對稱,所以我們只需要用每個下標和它對稱的下標上的數進行比較是否相等,如果不相等就不是回文,如果每個下標和對稱位都相等就是回文,簡單點可以直接從0循環到n-1,此時時間復雜度是O(N),但其實只需要循環到一半即可,因為如果超過一半就會重復了,沒有任何意義。

所以我們可以有以下解法

方法一

class Solution:
    def isPalindrome(self, x):
        # 將數字轉換為字符串
        x = str(x)
        # 得到字符串的長度
        n = len(x)
        # 對字符串進行迭代
        for i in range(n):
            # 判斷頭和尾是否相等并且頭要小于尾
            if x[i] != x[n - i - 1] and i < n - i - 1:
                return False
        return True

很明顯,此方法時間復雜度是O(N/2),算較好的方法

Longest Common Prefix

題目:Longest Common Prefix

Write a function to find the longest common prefix string amongst an array of strings..

題意分析:
求出一個字符串數組中所有字符串的最長共同前綴,如
['aaa','ab'] ==> a
['aaa'] ==> aaa
[]==> ''

思路分析

題目想要我們求出字符串數組中,所有字符串之間的共同的最長前綴,
想要求出最長的,這個最長的前綴,范圍肯定是0到所有字符串中最短的字符串長度,所以得到最短的字符串和它自身的長度是很關鍵的,如果沒有最短長度,我們根本不會知道循環的次數,如果隨意選擇一個字符串進行循環,如果這個字符串較長,就會造成越界錯誤

所以我們首先需要得到最短字符串和它自身的長度,來確定外循環次數,內循環去循環遍歷每個字符串。

要得到最長共同前綴,其實這個和在一個數組里求最大的數的思路一樣,我們需要先設第一個值為最大值,后面值分別與設的最大值相比較,如果比假設的最大值還要大,就需要更新假設最大值。

這里也一樣,我們首先假設最長共同前綴為最短字符串的前1個字符,在內循環中判斷每個字符的前i+1個子字符串是否等于假設的最長共同前綴,如果不相同,我們還需要判斷當前i+1是否等于1,如果等于,那就是第一個字符都不相同,那就需要返回空,如果都相同,需要判斷當前最長共同前綴是否等于最短字符串,如果等于,說明最長共同子串等于最短字符串,否則需要更新最長共同前綴,將其賦值為前i+1+1位的子字符串。進入下一次外循環。

在外循環中更新了最長共同前綴之后,在進入內循環判斷,如果前i+1位子串不等于最長共同前綴,那就得返回前i位子串,此時前為i為子串即為最長共同前綴。

所以我們可以有以下解法

方法一

class Solution:
    def longestCommonPrefix(self, strs):
        # 判斷字符串列表是否為空
        if not strs:
            return ''
        # 計算字符串列表中最短的字符串
        min_str = min(strs)
        # 計算最短字符串的長度
        min_length = len(min_str)
        # 初始令最長共同前綴字符串為最短字符串的第一個字符
        max_common_str = min_str[:1]
        for i in range(min_length):
            for str in strs:
                # 判斷字符串列表中每個字符串的前i+1位是否與最長共同字符串相同
                # 不同則判斷當前字符串是否為第1個,是則返回空,不是則返回前i位字符串
                if str[:i + 1] != max_common_str:
                    if i == 0:
                        return ''
                    return str[:i]
            # 當每個字符串前i+1位都與共同前綴字符相同時,判斷字符串是否最短字符串相同
            # 相同則返回最長共同前綴字符
            if min_str == max_common_str:
                return max_common_str
            # 不相同則返回前i+1+1位字符串(使字符串向后移動一位)
            max_common_str = min_str[:i + 1 + 1]
        return max_common_str

此解法時間復雜度是O(N^2),目前我想不到更好的解法。。但是leetcode能通過

Valid Parentheses

題目:Valid Parentheses

Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.

題意分析:
判斷一個只有字符'(', ')', '{', '}', '[' 和 ']'的字符串,并且每對括號都需要正確的關閉,也就是說括號需要成對出現

思路分析

判斷成對出現的東西,我們很容易想到棧(先進后出)這種數據結構。

括號亦是如此,如果出現左括號,我們就將其入棧,當在出現了右括號,我們在將其出棧,如果最后的棧為空,即括號剛好是成對出現的。

但我們還需要判斷三種括號之間的對應關系(即左小括號對應右小括號等),為了實現這種需求,在python里可以使用字典(java里可以使用map)存儲對應關系。

循環字符串時,如果當前字符為左字符串,則向棧(列表/數組)尾部加上這個字符,如果不等于左括號,則判斷此時棧是否為空或者當前的右括號字符在字典中所對應的左括號是否等于出棧的元素,如果不相等,則返回false

循環完畢還需要判斷棧是否為空,如果為空,則返回true,反之,返回false

所以我們可以有以下解法

方法一

class Solution:
    def isValid(self, s):
        '''
        :param s: str
        :return: bool
        '''
        left_char = '({['
        mp = {
            ')': '(',
            ']': '[',
            '}': '{'
        }
        # 初始化一個空列表作為棧
        stack = []
        # 循環遍歷字符串
        for i in s:
            # 如果字符是左括號就入棧
            if i in left_char:
                stack.append(i)
            else:
                # 如果也想加上對其他字符串匹配
                # if i in mp.keys():
                    # 棧為空或者傳入的右括號不等于棧尾的左括號,即不符合條件
                if not stack or mp[i] != stack.pop():
                    return False
        # 判斷棧是否為空,為空即成立
        if not stack:
            return True
        return False

用列表來替代模擬棧,時間復雜度為O(N),順利通過leetcode檢測

Merge Two Sorted Lists

題目:Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

題意分析:
將兩個已排序的鏈表合并,并返回一個新的鏈表,新鏈表應該是由兩個鏈表中的結點拼接起來的

思路分析

想要拼接鏈表,首先需要知道這個結點是什么樣的結構,很容易想到,python中的單鏈表的結點應該如下所示:

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

當然題中也給出了這個結構。有了這個結構,就能知道我們需要得到結點的值才能進行比較。

又由于題目要求我們使用其中的一個結點將兩個鏈表拼接起來,換句話說,就是將一個鏈表合并到另一個鏈表上,所以并不能創建一個新鏈表去進行操作。

當其中某一個鏈表為空時,只需要返回另一個鏈表即可,這種情況需要單獨討論

當兩個鏈表均不為空時,我們需要去比較結點兩個鏈表中結點的大小,當l1的結點值小于l2的結點時,我們就需要將l2合并到l1上,把l2的結點一個一個拼到l1上,知道l2為為空時,循環就可以結束了。這個過程是重復的,所以我們這里可以使用遞歸操作,反之,當l2的結點小于l1時,就把l1拼接到l2上

所以我們可以有以下解法

方法一

class Solution:
    def mergeTwoLists(self, l1, l2):
        '''
        :param l1: ListNode
        :param l2: ListNode
        :return: ListNode
        '''
        # 如果l1或l2有一個為空,則返回另一個
        if not l1 or not l2:
            return l1 or l2
        # 比較l1和l2的值的大小
        if l1.val < l2.val:
            # 將l2遞歸到l1上
            l1.next = self.mergeTwoLists(l1.next, l2)
            return l1
        else:
            # 將l1遞歸到l2上
            l2.next = self.mergeTwoLists(l2.next, l1)
            return l2

用了遞歸的方式,減少了我們需要處理的循環等等

Remove Duplicates from Sorted Array

題目:Remove Duplicates from Sorted Array

Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

例子:

Given input array nums = [1,1,2]
Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn't matter what you leave beyond the new length

題意分析:
去除有序數組中的重復元素,并返回去重之后的數組的長度

思路分析

由于我使用的是python,我首先想到的是用set集合去重,然后用len計算長度,立馬興奮的寫下一行代碼

len(set(nums))

然而在這里會報錯,所以只能考慮其他的辦法。

還很容易想到的是用一個列表,字典之類的將我們遍歷過的元素存起來,然后在用之后的元素與之比較,查看是否存在,存在就忽略,最后計算字典或者列表中元素的數量就能得到我們所需要的長度,但是同樣與題目要求不符,題目要求不能使用分配額外的空間去解決。所以還得想別的辦法

首先,數組或列表為空時,返回0,這個需要單獨討論,遍歷這個列表是必須的。

我們可以假設新列表的長度為0,然后我們就能同時得到列表中第一個元素的值,在循環中我們可以用下一個與之比較,如果不一樣,就將假設的新列表的長度+1,同時,由于有元素不一樣,我們需要將新元素賦給之前相同的元素,也就是索引為新列表長度的元素,由于是排序的列表,我們不用擔心,在未遍歷的元素中還有之前已經遍歷過的相同的元素。就這樣從第二個開始遍歷到最后一個,就能得到新列表的長度,但是由于我們是新列表的長度初始設為0,遍歷又是從1開始,所以這個列表的長度最終應該+1

所以我們可以有以下解法

方法一

class Solution:
    def removeDuplicates(self, nums):
        '''
        :param nums: list[int]
        :return:int
        '''
        # 如果數組為空,則返回0
        if not nums:
            return 0
        new_length = 0
        length = len(nums)
        # 從1到n-1開始循環遍歷
        for i in range(1, length):
            # 如果i不等于nums[now_length](其實是i-1)
            if nums[i] != nums[new_length]:
                new_length += 1
                nums[new_length] = nums[i]
        return new_length + 1

這樣我們就可以不用額外的空間,并且時間復雜度只有O(N-1)

Remove Element

題目:Remove Element

Given an array and a value, remove all instances of that value in place and return the new length.
Do not allocate extra space for another array, you must do this in place with constant memory.
The order of elements can be changed. It doesn't matter what you leave beyond the new length.

例子:

Given input array nums = [3,2,2,3], val = 3
Your function should return length = 2, with the first two elements of nums being 2

題意分析:
題意為給你一個數組,再給你一個值,刪除所有和這個值相等的元素,返回新列表的長度,要求不能在使用額外的數組,只能操作這一個數組。

思路分析

本來我想的很簡單,既然只是要返回長度,那我也可以不刪除,只計算長度啊,抱著僥幸的心里嘗試了最簡單的辦法,聲明一個長度的變量,并設置初始值為0,循環遍歷數組中所有元素,如果元素不與目標值相等就+1。提交之后發現并不能通過,那就是說,我們在返回長度的同時,也需要把元數組進行刪除。

既然要刪除元素,我想到了之前做過的Remove Duplicates from Sorted Array這一題,只不過這題要求是去除重復元素,同樣都是去除元素,思想也有些類似,這題可以想象成已經給你了一個重復元素,我們我們可以套用之前的解法,做一點變化即可。

同樣聲明一個長度為0,因為是刪除指定元素,所以數組為空的時候也不用擔心,那就返回0嘛,所以這次也不需要對0進行單獨討論了,同樣我們需要對數組進行循環遍歷,如果該下標元素不等于目標值的話,我們就把該下標元素賦值給聲明的長度作為下標的元素,然后將長度+1,這樣我們就可以完成操作了。在程序最后返回長度即可。

所以我們可以有以下解法

方法一

class Solution:
    def removeElement(self, nums, val):
        length = 0
        for i in range(len(nums)):
            if nums[i] != val:
                nums[length] = nums[i]
                length += 1
        return length, nums

這樣我們就可以不用額外的空間,時間復雜度為O(N)

Search Insert Position

題目:Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.

例子:

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0

題意分析:
一個有序數組,一個值,首先需要判斷值是否在數組中,如果存在,即返回該值在數組中的索引值,如果不存在,就需要返回這個值應該在的地方。

思路分析

這題算很簡單的了,只需要一次循環即可,循環遍歷所有元素,由于列表是有序的,所以直到有元素第一次大于目標值時,就已經能夠知道該值不在數組中,當然,當第一次大于該值時,此時的索引也就是該值應該存在的地方。

當然,等于該值的情況需要單獨討論,也可以在該循環中加以判斷即可,由于我使用的是python,首先想到的就是in操作,其可以直接判斷是否存在,存在在用index方法得到索引。

還有一種極端情況,如果上述情況都不成立,那就是目標值大于列表中最大的,也就是如果該值在列表中,其應該在列表的下一位,也就是列表的長度。

所以我們可以有以下解法

方法一

class Solution:
    def removeElement(self, nums, val):
        length = 0
        for i in range(len(nums)):
            if nums[i] != val:
                nums[length] = nums[i]
                length += 1
        return length, nums

這樣我們就可以不用額外的空間,時間復雜度為O(N)

Maximum Subarray

題目:Maximum Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

例子:

given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6

題意分析:
求出一個整形列表中幾個連續元素的和

思路分析

想要得到和,首先我們肯定要求和,想知道若干個元素的和,還得求出最大的和,意味著我們肯定要循環。

方法一:
很容易想到我們可以先先計算一個元素的和,然后循環得到這個元素與后續所有元素的和,并求出其中的最大值,這很簡單,只需要當和大于假定的最大值時,更新最大值即可。這就得到了以一個元素開始與后續子元素其中的最大值。

想要得到整個列表中哪幾個連續元素的和最大,我們還需要對所有元素進行循環,也就是在內循環以某個元素開始的最大值,在外循環得到以所有元素的最大值。

因為方法一的進行了兩次循環,時間復雜度較高,為此我們需要想辦法進行一次循環就得到我們需要的值。

方法二:
要達到目的,循環肯定少不了,既然我們不需要得到是哪幾個元素的和最大,我們也就沒必要進行兩此循環,來得到是從那個索引開始到那個索引結束。

首先,我們聲明兩個變量,一個為循環當前的最大值,一個為我們需要的最大值,初始都將他們賦為列表的第一個元素(需要對為列表單獨討論)。

我們不需要得到元素列表,所以直接迭代列表元素即可,計算當前元素與當前的最大值+當前元素的和,并將他們倆之間的最大值賦值給當前最大值。

然后再將當前最大值與需要的最大值進行比較,把其中的最大值賦值給需要的最大值。循環結束就能得到我們需要的。

所以我們可以有以下解法

方法一

class Solution:
    def maxSubArray(self, nums):
        """
        計算列表中連續子數組的最大和
        :param nums: list[int]
        :return: int
        """
        start = 0
        stop = 0
        length = len(nums)
        if length == 1:
            return sum(nums)
        largest_sum = nums[0]
        for i in range(0, length):
            max_sum = nums[0]
            for j in range(i, length):
                ij_sum = sum(nums[i: j + 1])
                if ij_sum > max_sum:
                    stop = j
                    max_sum = ij_sum
            if max_sum > largest_sum:
                start = i
                largest_sum = max_sum
        return largest_sum

時間復雜度較高為O(N^2),但可以得到最大和的元素列表

方法二

class Solution:
    def maxSubArray(self, nums):
        """
        計算列表中連續子數組的最大和
        :param nums: list[int]
        :return: int
        """
        if not nums:
            return 0
        cur_sum = nums[0]
        max_sum = nums[0]
        for i in nums[1:]:
            # 計算當前的和與i相加之后的和比較的最大值
            cur_sum = max(i, cur_sum + i)
            # 計算當前和與最大和比較的最大值
            max_sum = max(max_sum, cur_sum)
        return max_sum

一次循環,時間復雜度為O(N),不能輕易得到元素列表

Count and Say

題目:Count and Say

The count-and-say sequence is the sequence of integers with the first five terms as following:

1.     1
2.     11
3.     21
4.     1211
5.     111221

1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
Given an integer n, generate the nth term of the count-and-say sequence.

例子:

Input: 1
Output: "1"

Input: 4
Output: "1211"

題意分析:
第n次結果是對n-1次結果的解釋。例如第4次的結果為1211,參照第3次結果,可以解釋為一個2,一個1,就形成了1211,一次類推

思路分析

在我們掌握了規律之后,我們發現下一次的結果總由上一次的結果所決定,很容易想到可以用遞歸處理,如果采用遞歸,當然我們也需要知道結束標志,不然就會一直死循環下去了,這里很明顯,結束標志就是當n為1或者0時,分別返回1或者空。

當需要求第n次結果時,我們可以獲取遞歸調用第n-1次的結果進行處理,對上一次計算結果進行處理,這里就是對上一次計算結果解釋。

所以我們可以有以下解法

方法一

class Solution:
    def countAndSay(self, n):
        """

        :param n: int
        :return: str
        """
        if n == 0:
            return ''
        if n == 1:
            return '1'
        # 得到上一次的結果
        n1_str = self.countAndSay(n - 1)
        # 末尾字符賦值為上一次結果的第一個字符
        last = n1_str[0]
        cnt = 1
        n_str = ''
        # 從索引1開始迭代
        for i in range(1, len(n1_str)):
            # 如果當前元素等于初始末尾字符(上一次結果的第一個字符)
            if n1_str[i] == last:
                cnt += 1
            else:
                n_str = n_str + str(cnt)
                n_str = n_str + last
                # 將數量重置為1
                cnt = 1
                last = n1_str[i]
        n_str = n_str + str(cnt)
        n_str = n_str + last
        return n_str

這樣就用遞歸的方式很簡單的得到了結果。

當然我們也可以用求下一次結果的方式,只需要執行n-1次即可。

Count and Say

題目:Count and Say

Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string.
If the last word does not exist, return 0.
Note: A word is defined as a character sequence consists of non-space characters only.

例子:

Given s = "Hello World",
return 5.

題意分析:
題目要求我們求字符串中最后一個單詞的長度,并且這個字符串每個單詞之間是由空格連接,當最后一個單詞不存在時,返回0。

思路分析

這道題目可以說非常簡單了,唯一的混淆點就是對空格的處理,當末尾有空格時,中間有空格時,處理都會變的麻煩。

但是題目已經說明末尾的空格并不計算,所以我們可以首先將前后的空格去掉,然后根據單詞分割符空格將字符串進行切割,然后取最后一部分計算長度即可。

所以我們可以有以下解法

方法一

class Solution:
    def lengthOfLastWord(self, s):
        """
        返回字符串中最后一個單詞的長度
        :param s: str
        :return: int
        """
        # 先去掉首尾的空格
        # 在按空格切割字符串轉換為列表
        # 取列表最后一個元素計算長度
        return len(s.strip().split(' ')[-1])

代碼非常短,只需要一行就可以解決。效率也是很高的

Add Binary

題目:Add Binary

Given two binary strings, return their sum (also a binary string).

例子:

a = "11"
b = "1"
Return "100".

題意分析:
題目很好理解,只是個二進制加法。

思路分析

既然要求二進制加法,我們可以利用計算機內部的實現來直接求得結果,但是這樣對大部分人來說比較困難。

我們還可以先將二進制轉為10進制,然后就可以直接用+號直接加了,理解起來非常簡單,然后得出結果后在將其轉為2進制即可。

所以我們可以有以下解法

方法一

class Solution:
    def addBinary(self, a, b):
        """
        二進制加法
        :param a:
        :param b:
        :return:
        """
        a, b = int(a, 2), int(b, 2)
        # 由于bin()方法轉為的二進制會有0b前綴,所有我們需要用字符串切到2之后
        return bin(a+b)[2:]

Sqrt(x)

題目:Sqrt(x)

Implement int sqrt(int x).
Compute and return the square root of x.

題意分析:
這題考sqrt()方法的實現,也就是求平方根

思路分析

求平方根,其實是個數學問題,我們可以想一下在數學里面是如何處理的。

但作為編程題,其實我們可以調用標準庫中的sqrt()函數直接得出結果,我們也可以去查看其中的源碼。

還可以去求0.5次方的結果。

所以我們可以有以下解法

方法一

class Solution:
    def mySqrt(self, x):
        """
        計算平方根
        :param x: int
        :return: int
        """
        import math
        return int(math.sqrt(x))

調用math庫中的sqrt函數,雖然在這里也能通過,但是我覺得有點不符合題意

方法一

class Solution:
        def mySqrt(self, x):
        """
        計算平方根
        :param x: int
        :return: int
        """
        return int(x ** 0.5)

這種方法使用的是求0.5次方。

Climbing Stairs

題目:Climbing Stairs

You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Note: Given n will be a positive integer.

題意分析:
題目相當于a到b點有n步,你每次可以選擇走一步或兩步,求可以有多少種方式可以走到終點

思路分析

這題,筆者最開始把題目抽象成了x+2y=n這個方程,然后去找有多少組整數解了,后來一想,發現并不是這樣,因為上面那個方程只計算了走一步和走兩步的次數,并沒有考慮先后的順序,思路就斷了。

然后筆者在紙上,分別列舉了當n=1,2,3,4...時的結果數,發現了一個規律,每一次的結果等于上一次+上上次的結果的和,類似與斐波那契數列。

所以我們可以有以下解法

方法一

class Solution:
    def climbStairs(self, n):
        """

        :param n: int
        :return: int
        """
        a = b = 1
        for i in range(n):
            a, b = b, a + b
        return a

雖然筆者也不知道結果為什么,希望有讀者能從數學上給我解釋下。

Remove Duplicates from Sorted List

題目:Remove Duplicates from Sorted List

Given a sorted linked list, delete all duplicates such that each element appear only once.

例子:

Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.

題意分析:
在一個已排序的單鏈表中,刪除所有重復的元素,每個元素只能保留一個

思路分析

為了刪除重復元素,我們需要遍歷整個單鏈表,又由于我們不知道循環的次數,只知道結束條件為結點為空,所以我們需要使用while循環,

在循環中我們還需要嵌套一層while循環,判斷當前結點的下一個結點是否存在并且下一個結點的值是否等于下下個結點的值,如果等于就將下下個結點賦值給當前結點的下一個結點。這部的作用其實就是將重復的元素都跳過。

在外循環中將當前結點的下一個結點賦值給當前結點,最后返回單鏈表的頭結點即可。

所以我們可以有以下解法

方法一

class Solution:
    def deleteDuplicates(self, head):
        """
        有序單鏈表去重
        :param head: ListNode
        :return: ListNode
        """
        current = head
        # 如果當前結點不為空
        while current:
            # 如果當前結點的下一個結點存在
            # 并且當前結點的值等于下一個結點的值
            while current.next and current.val == current.next.val:
                # 當前結點的下一個結點等于當前結點的下下個結點
                current.next = current.next.next
            # 再降當前結點的下一個結點賦值給當前結點
            current = current.next
        # 返回已經去重的單鏈表
        return head

Merge Sorted Array

題目:Merge Sorted Array

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.

題意分析:
給定兩個已排序的整形列表nums1和nums2,將nums2合并到nums1上作用一個排序的列表。

思路分析

如果m>0 n>0時,如果nums1的m - 1一個元素的值大于等于nums2的n - 1個元素值則我們需要把nums1的m-1的值賦值給nums[m+n-1],然后將m減一即可,否則需要將nums2的n-1的值賦值給nums1[m-n-1],然后將n減一。

如果只有n大于0,則只需把nums2的前n項賦值給nums1的前n項

所以我們可以有以下解法

方法一

class Solution:
    def merge(self, nums1, m, nums2, n):
        """
        將列表nums2合并到nums1上
        :param nums1: list[int]
        :param m: int
        :param nums2: list[int]
        :param n: int
        :return: void
        """
        while m > 0 and n > 0:
            if nums1[m - 1] >= nums2[n - 1]:
                nums1[m + n - 1] = nums1[m - 1]
                m -= 1
            else:
                nums1[m - n - 1] = nums2[n - 1]
                n -= 1
        if n > 0:
            nums1[:n] = nums2[:n]

Same Tree

題目:Same Tree

Given two binary trees, write a function to check if they are equal or not.
Two binary trees are considered equal if they are structurally identical and the nodes have the same value.

題意分析:
讓我們判斷兩個二叉樹是否相同,相同的標準只需要各位置上的元素值相等即可

思路分析

想要判斷各個結點上的值是否相等,我們需要去遍歷整棵樹。

在二叉樹方面,我們一般使用遞歸的方法去遍歷,先判斷當前結點是否為空,如果不為空,可以在遍歷的過程中不斷的比較每個結點上的元素的值。如果當前結點的值也相同,我們需要同時比較當前結點的左子樹和和右子樹。

還有一種當兩顆樹都為空時,需要單獨討論,此時兩棵樹也是符合題意的相等

所以我們可以有以下解法

方法一

class Solution:
    def isSameTree(self, p, q):
        """
        判斷兩個二叉樹是否相同(值相同即相同)
        :param p: TreeNode
        :param q: TreeNode
        :return: bool
        """
        # 如果p和q都不為空
        if p and p:
            # 當前結點的值是否相等
            if p.val == q.val:
                # 判斷當前結點的下一個左右結點是否相等
                return self.isSameTree(q.left, p.left) \
                       and self.isSameTree(q.right, p.right)
        # 如果p和q均為空
        if not p and not q:
            return True
        return False

使用遞歸的方法使理解起來很容易,邏輯上也相對簡單。

Symmetric Tree

題目:Symmetric Tree

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

例子:

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:

    1
   / \
  2   2
 / \ / \
3  4 4  3
But the following [1,2,2,null,3,null,3] is not:
    1
   / \
  2   2
   \   \
   3    3

題意分析:
給出一個二叉樹,檢查這個二叉樹是否鏡像對稱(左右對稱)

思路分析

想要判斷二叉樹是否左右對稱,也就是左子樹等于右子樹,或者當前結點都為空。

對結點為空,我們需要單獨討論。

為了好理解,我們可以抽象出一個函數,傳入兩個樹,判斷這兩個樹是否是鏡像的,在調用時,我們只需要均傳入當前樹的根結點即可。

所以我們可以有以下解法

方法一

class Solution:
    def isSymmetric(self, root):
        """
        判斷一顆樹是否是鏡像樹
        :param root: TreeNode
        :return: bool
        """
        return self.isMirror(root, root)

    def isMirror(self, tree_node1, tree_node2):
        """
        判斷兩棵樹是否鏡像
        :param tree_node1: TreeNode
        :param tree_node2: TreeNode
        :return: bool
        """
        # 如果兩個葉子結點均為空
        if not tree_node1 and not tree_node2:
            return True
        # 如果只有一個葉子結點為空
        if not tree_node1 or not tree_node2:
            return False
        # 當前葉子結點的值相等,并且一顆樹的左子樹等于另一顆樹的右子樹
        return (tree_node1.val == tree_node2.val) \
               and self.isMirror(tree_node1.right, tree_node2.left) \
               and self.isMirror(tree_node1.left, tree_node2.right)

分別對結點均為空或者一個為空的狀態左討論,最后用遞歸的方式調用該樹的左子樹和右子樹。

Maximum Depth of Binary Tree

題目:Maximum Depth of Binary Tree

Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

題意分析:
求出樹的最大深度。

思路分析

想求最大深度,我們只需遞歸左右子樹找出哪個子樹的深度更深即可,但由于還有根結點,所以在求出兩個子樹的最大深度之后還需要+1.

對根結點為空時,需要單獨討論,返回0即可

所以我們可以有以下解法

方法一

class Solution:
    def maxDepth(self, root):
        """
        計算樹的最大深度
        :param root: TreeNode
        :return: int
        """
        # 如果根結點為空返回0
        if not root:
            return 0
        # 計算左右子樹的中的最大深度,加上根節點
        return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

注:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容