LeetCode刷題日記

最近正在找實習,發(fā)現(xiàn)自己的算法實在是不能再渣渣,在網(wǎng)上查了一下,發(fā)現(xiàn)大家都在刷leetcode的題,于是乎本渣渣也開始了刷題之路,主要用的是python寫的代碼。寫個日記記錄一下每天刷題的心路歷程,順便記錄學習到的知識。

#1.TwoSum

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.
Example:
Given nums = [2, 7, 11, 15], target = 9,Because nums[0] + nums[1] = 2 + 7 = 9,return [0,1].

一開始想的是兩個for循環(huán),暴力枚舉,于是寫出了如下代碼...

# coding: utf-8
class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        for i in range(0, len(nums)):
            for j in range(i+1, len(nums)):
                if nums[i] + nums[j] == target:
                    return [i, j]

上面算法復雜度為O(n^2),本來沒抱太大希望,結果放上去居然AC了。然后去評論區(qū)看了一下,全是O(n)的解法。定義一個字典d{},先計算m = target - nums[i],如果字典里沒有鍵為n的值,則存入d[num[i]] = i,如果下次遇到目標數(shù),我們就可以通過字典找到另一個加數(shù)的索引值,返回[d[m], i],這樣就做到了以空間換時間。寫出下面的代碼:

# coding: utf-8
class Solution:
def twoSum(self, nums, target):
        """
        :typenums: List[int]
        :typetarget: int
        :rtype: List[int]
        """
        d = {}
        for i, vin enumerate(nums):
             m = target - v
            if d.get(m)is not None:
                 return [d[m], i]
            else:
                 d[v] = i

兩個代碼的運行時間比為5392ms:76ms...


#2.Add Two Numbers

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example
Input:(2 -> 4 -> 3) + (5 -> 6 -> 4)
Output:7 -> 0 -> 8
Explanation:342 + 465 = 807.

這題想到的是直接法,遍歷兩個輸入鏈表,用字符串存起來,逆序,然后轉換為整數(shù)相加,把結果再逆序存進鏈表中,非常直接的解法了。。。時間復雜度O(n),代碼如下

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

class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        if l1 is None or l2 is None:
            return None
        n1 = ""
        n2 = ""
        p = l1
        q = l2
        while p is not None:
            n1 += str(p.val)
            p = p.next

        while q is not None:
            n2 += str(q.val)
            q = q.next

        n1 = n1[::-1]
        n2 = n2[::-1]
        res = str(int(n1) + int(n2))
        head = ListNode(0)
        p = None
        pre = None
        res = res[::-1]
        for i, s in enumerate(res):
            if i == 0:
                head.val = int(s)
                p = head
            else:
                p = ListNode(int(s))
                pre.next = p
            pre = p
        return head

提交之后AC了,但我覺得這肯定不是最優(yōu)解,因為這里逆序了三遍,數(shù)量大的時候還速度會很慢,于是去看了題解,意思是設定一個進位carry=0,在一個while循環(huán),如果p->val + q->val + carry > 10,那么next.val加上和除以10的商的整數(shù)部分,當前節(jié)點值為其模10后的余數(shù)。還學到了一個python的函數(shù)divmod(a, b),返回的是(a//b, a %b),即a除以b的商整數(shù)部分,a對b取模。重寫代碼如下

    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        carry = 0
        head = p = ListNode(0)
        while l1 or l2 or carry:
            v1 = v2 = 0
            if l1:
                v1 = l1.val
                l1 = l1.next
            if l2:
                v2 = l2.val
                l2 = l2.next
            carry, val = divmod(v1+v2+carry, 10)
            p.next = ListNode(val)
            p = p.next
        return head.next

新代碼簡短精悍!比原來的簡單多啦,但是不知道為什么runtime比原來還多一點...雖然只多了32ms,但是還是有些失望難道白優(yōu)化了??不管了,反正代碼好看很多。


#3.Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb", the answer is "abc", which the length is 3.
Given "bbbbb", the answer is "b", with the length of 1.
Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

最長非重復子串問題,看起來很簡單,一開始居然想錯了,想成了求兩個相同字符串之間的距離的最大值,嘩啦嘩啦寫了以下代碼:

# coding: utf-8
class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        if len(s) == 0:
            return 0
        maxium = 1
        d = {}
        for t in s:
            d[t] = 1
            for key in d.keys():
                d[key] = d[key] + 1 if key != t else d[key]
                maxium = d[key] if d[key] > maxium else maxium
        return maxium

結果當然是嘩啦嘩啦的WA了,其實問題沒有那么復雜,是我一心想著最優(yōu)化然而想到的算法是錯的。WA了幾次之后發(fā)現(xiàn)不對勁,其實思路一開始就是錯的。從頭開始想,這題其實回歸純真、暴力就好(沒錯,我的想法就是很暴力)。定義空字符串res,從頭開始遍歷輸入的字符串,遇到res中沒有的字符就加進去,有的話就截取上一個相同的字符之后的字符串再加入新的字符,每趟循環(huán)計算一次res的長度,獲取最大值。重寫的代碼如下:

# coding: utf-8
class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        maxium = 0
        res = ""
        for t in s:
            if t not in res:
                res += t
            else:
                i = res.index(t)
                res = res[i+1:] + t
            maxium = len(res) if len(res) > maxium else maxium
        return maxium

放上去果然AC了,簡單,粗暴。如果所有問題都可以這么暴力就好了。時間復雜度是O(n),因為用到了python的not in和index還有字符串復制,如果換成其他語言可能更加復雜一些。


#4.Median of Two Sorted Arrays

There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5

left Ci right
a0, a1...ai-1 i ai, ai+2...an
b0, b1...bj-1 j bj, bj+2...bm

兩個有序數(shù)組求它們合并之后的中值,要求時間復雜度為O(log(m+n)),思來想去只能想到O((m+n)/2)的算法,也就是暴力枚舉的方法。于是出去搜索了一下,發(fā)現(xiàn)這是一個經(jīng)典的分治算法,在這里復述一下他的思路。
我們可以通過割的方法將一個有序數(shù)組分為兩個部分,比如說[1, 4, 7, 9]這個數(shù)組,我們在位置C上割一刀,割完后數(shù)組左邊有C個數(shù),那么數(shù)組左邊部分最大的數(shù)就是nums[C-1],假設C=2,那么這個數(shù)組就被分為[1, 4, / 7, 9]兩個部分。如果數(shù)組的長度為單數(shù)呢?在[2, 3, 5]上令割C=2,那么3將同時屬于左右兩部分,結果為[2, 3,/ 3, 4]。在單個數(shù)組中,要求數(shù)組的中值,我們可以在C=len(nums)/2的位置割一刀,求出中值為左邊最大的數(shù),即mid = nums[len(nums)/2 - 1]。
下面我們來看有兩個數(shù)組的情況。我們要求兩個數(shù)組的中值,就是求兩個數(shù)組合并后在C = len(nums1)+len(nums2)/2 位置上割一刀,左邊部分的最大值。其實我們不用真的合并這兩個數(shù)組,而是用二分的方法求出割的位置,怎么求呢?

left Ci right
a0, a1...ai-1 i ai, ai+2...an
b0, b1...bj-1 j bj, bj+2...bm

上表表示分別在i和j的位置割兩個數(shù)組,我們令上表中的L1 = ai-1,L2 = bj-1, R1 = ai, R2 = bj。顯然R1 > L1, R2 > L2。若L1 < R1 && L2 < R2,那么表示左邊的數(shù)全部小于右邊的數(shù),如果此時左邊共有k個數(shù),那么左邊最大的數(shù)就為我們要求的數(shù)。
為了統(tǒng)一計算數(shù)組長度為奇數(shù)或偶數(shù)的情況,我們引入“虛擬數(shù)組“的概念。用‘#’填充數(shù)組,比如[1, 4, 7, 9]填充為[#, 1, #, 4, #, 7, #, 9 #],這樣無論數(shù)組的長度為奇數(shù)還是偶數(shù),填充后數(shù)組長度必為2n+1的奇數(shù)。這樣做的好處是,當我們確定割的位置時,割的左邊對應原數(shù)組位置總為L = (C - 1)/2,右邊的位置總為C/2,比如在數(shù)組[#, 1, #, 4, #, 7, #, 9 #]中:
若割的位置為4,則L = (4 - 1) / 2 = 1,R = 4 / 2 = 2,而1和2正好是原數(shù)組中4和7的位置。
我們不用真正的在數(shù)組中添加#,只需要在二分開始的時候將高位設置為2n+1就可以。
如果我們使用虛擬數(shù)組的時候,那么合并后的數(shù)組總長度為2n+2m+2,中值位置為n+m+1。令i為nums1的割位置,j為nums2的割位置,那么當取得中值時必有i+j = n+m+1,因此我們只要找到同時符合 nums1[(i-1)/2] < nums2[j/2] && num2[(j-1)/2] < nums1[i/2]的i和j,就能找到中值。思路已經(jīng)明確了,我們可以開始寫代碼

# coding: utf-8
import sys
class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        n = len(nums1)
        m = len(nums2)
        if n > m:
            return self.findMedianSortedArrays(nums2, nums1)

        L1, L2, R1, R2, low = 0, 0, 0, 0, 0
        high = 2*n
        while low <= high:
            c1 = int((low + high)/2)
            c2 = m + n - c1
            L1 = nums1[int((c1-1)/2)] if not c1 == 0 else -sys.maxsize
            L2 = nums2[int((c2-1)/2)] if not c2 == 0 else -sys.maxsize
            R1 = nums1[int(c1/2)] if not c1 == 2*n else sys.maxsize
            R2 = nums2[int(c2/2)] if not c2 == 2*m else sys.maxsize

            if L1 > R2:
                high = c1 - 1
            elif L2 > R1:
                low = c1 + 1
            else:
                break
        return (max(L1, L2) + min(R1, R2)) / 2.0

最終AC了,真的好難想啊,代碼也不好寫,不過又學到了一些東西,也算是有一點進步吧。


#5.Longest Palindromic Substring

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example:
Input: "cbbd"
Output: "bb"

最長回文子串問題,想到的是從中心開始往兩邊搜索的思路,思路分成兩部分,分別計算子串長度為奇數(shù)即aba形態(tài)和子串長度為偶數(shù)即abba形態(tài)的最長長度,取其最大值。首先用一個for循環(huán)遍歷每一個可能的中心點,然后用一個while循環(huán)從中心點出發(fā),如果兩邊的字符相同則count+2,否則跳出循環(huán),記錄count的最大值和最長子串的起始位置,最后返回子串[start:start+maxium],寫出代碼:

# coding: utf-8
class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        maxium = 1
        start = 0
        for i in range(len(s)):
            # aba
            j = i - 1
            k = i + 1
            count = 1
            while j >= 0 and k < len(s) and s[j] == s[k]:
                count += 2
                if count > maxium:
                    maxium = count
                    start = j
                j -= 1
                k += 1
        for i in range(len(s)):
            # abba
            j = i
            k = i + 1
            count = 0
            while j >= 0 and k < len(s) and s[j] == s[k]:
                count += 2
                if count > maxium:
                    maxium = count
                    start = j
                j -= 1
                k += 1

        return s[start:start+maxium]

時間復雜度為O(n^2),提交后AC了。然后取看題解,有一種Manacher的算法,時間復雜度為O(n),看了半節(jié)課沒看懂,在這貼個鏈接以后有時間再看[Manacher算法詳解]。(https://www.cnblogs.com/z360/p/6375514.html)


#6.ZigZag Conversion

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".

這題找規(guī)律,首尾兩行的規(guī)律比較好找,中間的行數(shù)規(guī)律有奇偶數(shù)之分,分析了一會寫了代碼:

# coding: utf-8
class Solution:
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        n = len(s)
        if numRows == 1 or n == 0:
            return s
        step = 2*numRows - 2
        res = []
        for i in range(numRows):
            rs = ""
            if i % (numRows-1) == 0:
                # the first or the last row
                index = i % numRows
                while index < n:
                    rs += s[index]
                    index += step
                res.append(rs)
            else:
                # the middle rows
                index = i % numRows
                count = 0
                while index < n:
                    rs += s[index]
                    if count % 2 == 0:
                        index += step - 2 * (i % numRows)
                    else:
                        index += 2 * (i % numRows)
                    count += 1
                res.append(rs)
        result = ""
        for i in range(numRows):
            result += res[i]
        return result

提交之后AC了,時間復雜度是O(n*m),但是覺得自己找規(guī)律的時間有點長,希望能再提高吧。


#7.Reverse Integer

Given a 32-bit signed integer, reverse digits of an integer.
Example 1:
Input: 123
Output: 321
Example 2:
Input: -123
Output: -321
Example 3:
Input: 120
Output: 21
Note:
Assume we are dealing with an environment which could only hold integers within the 32-bit signed integer range. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

翻轉整數(shù),先把輸入轉化為字符串,如果有符號,先把符號提取出來,然后將剩下的字符串翻轉后再加上符號,最后判斷是不是在32位int的范圍內,python的代碼幾行就寫好了。

# coding: utf-8
class Solution:
    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
        s = str(x)
        index = 1 if s[0] == "-" or s[0] == "+" else 0
        s = s[0] + s[index:][::-1] if index else s[::-1]
        res = int(s)
        if -2147483648 < res < 2147483647:
            return res
        else:
            return 0

果斷AC了,時間復雜度O(n),翻轉字符串還是比較耗時的,不過這也算簡單題,如果用其他語言應該復雜一點。


#8.String to Integer (atoi)

Implement atoi to convert a string to an integer.
Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
Requirements for atoi:
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

實現(xiàn)一個atoi函數(shù),題目好長,主要是考慮的情況有很多,其實也不是很難,就是要注意一些地方,還好python的isdigit()函數(shù)和try except幫了大忙,代碼寫好很快就AC了,算法復雜度是O(n)

# coding: utf-8
class Solution:
    def isIntegerNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        if s.isdigit() or s == "-" or s == "+":
            return True
        else:
            return False

    def myAtoi(self, st):
        """
        :type st: str
        :rtype: int
        """
        r = ""
        status = False
        for c in st:
            if not status:
                if c == " ":
                    continue
                elif not self.isIntegerNumber(c):
                    break
                elif self.isIntegerNumber(c):
                    status = True
                    r += c
            else:
                if c.isdigit():
                    r += c
                else:
                    break
        try:
            r = int(r)
            if r > 2147483647:
                return 2147483647
            elif r < -2147483648:
                return -2147483648
            else:
                return r
        except:
            return 0

#9. Palindrome Number

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

題目很短!就是判斷一個數(shù)是否回文數(shù),要求不使用額外的空間。不能用額外的空間,那就不能將它轉換為字符串來做了,想了一個用除和模做的方法。首先計算它的數(shù)量級(10的多少次方),然后不斷將這個數(shù)除以其數(shù)量級,比較取整后的商和它與10的模,如果不相等表示該數(shù)的第一個數(shù)和最后一個數(shù)字不同,返回false。如果相等,則將該數(shù)減去其先前求出的商*數(shù)量級,再減去先前求出的模,然后除以10,得到去頭去尾的一個新數(shù),繼續(xù)判斷其是否為回文串。根據(jù)這個思路寫出的代碼:

# coding: utf-8
class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x < 0:
            return False
        l_size = 1
        s_size = 10
        while x / l_size >= 10:
            l_size *= 10

        while x > 0:
            first = x // l_size
            last = x % s_size
            if last != first:
                return False
            x -= l_size * first
            x -= last
            x /= 10
            l_size /= 100

        return True

一次就AC了,說明這個方法還是管用的,而且沒有用到多余的空間。


#10. Regular Expression Matching

實現(xiàn)一個能匹配.和*的正則表達式引擎,太難了。。。想了一個晚上,要考慮的情況太多,先放棄這一題。


#11. Container With Most Water

Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container and n is at least 2.

一開始理解錯了題目,以為是求梯形面積,WA一次之后發(fā)現(xiàn)題目不是這個意思,其實是求兩塊木板之間能裝多少水的面積,也就是短板的高度*x坐標的差。很快就寫了一個O(n^2)的思路,放上去果然超時了。


#include <cmath>
class Solution {
public:
    int maxArea(vector<int>& height) {
        int maxium = 0;
        for (int i=0; i<height.size(); i++){
            for (int j=i+1; j<height.size();j++){
                int m = height[j] < height[i]? height[j] : height[i];
                int area = m * (j - i);
                if (area > maxium)maxium = area;
            }
        }
        return maxium;
    }
    
};

然后想了一個O(n)的思路,先定義一個一維數(shù)組,里面放的是該坐標能找到的最長的木板的左邊,然后從左到右遍歷木板,如果遇到比自己能找到最長的木板更長的木板,則遞歸更新該數(shù)組。我是這么想的,因為是從左到右的遍歷,所以如果在右邊找到更長的木板,那么面積一定比原來找到的那個木板更大(我現(xiàn)在知道哪里錯了,前提條件應該是數(shù)組存的木板比自身短)。寫出以下代碼:

#include <cmath>
class Solution {
public:
    vector<int> highestPos;
    int maxArea(vector<int>& height) {
        highestPos.resize(height.size());
        for(int i=0;i<height.size()-1;i++){
            if(height[highestPos[i]] < height[i+1]){
                changeHighestIndex(i, i+1);
            }
        }
        int maxium = 0;
        for(int i=0;i<height.size();i++){
            int lowest = height[i] < height[highestPos[i]] ? height[i] : height[highestPos[i]];
            int area = lowest * abs(i-highestPos[i]);                       
            if(area > maxium)maxium = area;
        }
        return maxium;
    }
    void changeHighestIndex(int i, int newPos){
        if(highestPos[i] != newPos){
            int tmp = highestPos[i];
            highestPos[i] = newPos;
            changeHighestIndex(tmp, newPos);
        }
    }
    
};

放上去WA了,思考一會之后發(fā)現(xiàn)這個思路應該太復雜了,其實我可以從兩邊向中間遍歷,記錄最大值就好,這個思路清晰簡單,寫出來的代碼也很簡單。時間復雜度是O(n),一次就AC了。

#include <cmath>
class Solution {
public:
    int maxArea(vector<int>& height) {
        int low = 0;
        int high = height.size() - 1;
        int maxium = 0;
        
        while(low < high){
            int lowest = height[low] < height[high] ? height[low] : height[high];
            int area = lowest * (high - low);
            maxium = area > maxium ? area : maxium;
            
            if(height[low] > height[high]){
                high--;
            }else{
                low++;
            }
        }
        return maxium;
    }
};

#12. Integer to Roman

Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.

將整數(shù)轉換為羅馬數(shù)字字符串,為此還學習了一波羅馬數(shù)字。挺簡單的題,結果邊界值0的時候卡住了,改了挺久,不應該啊。

#include <iostream>
#include <string>
using namespace std;
class Solution {
public:
    string intToRoman(int num) {
        string all[4][10] = {
            {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"},
            {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"},
            {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"},
            {"", "M", "MM", "MMM"}
        };
        
        
        int size = 10;
        string res = "";
        int count = 0;
        while(num*10 / size){
            int left = num % size;
            res = all[count][left*10/size] + res;
            num = num - left*10 / size;
            size *= 10;
            count += 1;
        }
        return res;
    }
};

#13. Roman to Integer

Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.

上一題的反向,我覺得更簡單一些,代碼很快就AC了,時間復雜度O(n)。

class Solution {
public:
    int romanToInt(string s) {
        int worth[26];
        int a = 'A';
        worth['M'-a] = 1000;
        worth['D'-a] = 500;
        worth['C'-a] = 100;
        worth['L'-a] = 50;
        worth['X'-a] = 10;
        worth['V'-a] = 5;
        worth['I'-a] = 1;
        
        int i = s.length()-1;
        int total = 0;
        while(i>=0){
            if(i==0){
                total += worth[s[i]-a];
                break;
            }
            int A = worth[s[i]-a];
            int B = worth[s[i-1]-a];
            if(A<=B){
                total += A;
                i -= 1;
            }else{
                total = total + A - B;
                i -= 2;
            }
        }
        return total;
    }
};

#14. Longest Common Prefix

Write a function to find the longest common prefix string amongst an array of strings.
尋找給出字符串列表的最長共同前綴,思路是一開始最長的前綴是第一個字符串,然后遍歷每一個字符串,如果某個字符串在某位和當前的最長前綴不同,則最長前綴截取為前面相同的部分,寫出代碼:

# coding: utf-8
class Solution:
    def longestCommonPrefix(self, strs):
        """
        :type strs: List[str]
        :rtype: str
        """
        if len(strs) == 0:
            return ""
        prefix = strs[0]
        for v in strs:
            if len(prefix) == 0:
                return ""
            if len(v) < len(prefix):
                prefix = prefix[:len(v)]
            for i in range(len(prefix)):
                if v[i] != prefix[i]:
                    prefix = prefix[:i]
                    break
        return prefix

處理空字符串的情況后之后就AC了,時間復雜度O(n),這題不是很難。


#15. 3Sum

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.

找出給出數(shù)組中的三個數(shù),使得它們的和為0,要求結果去掉相同的情況。這題和第一題有點像,所以我想沿用第一題的思路,設置一個以差值為鍵的字典,這樣將O(n3)的問題化為O(n2)。然而這題的結果有很多,這種做法會出現(xiàn)很多重復的代碼,去重雖然能實現(xiàn)但是太復雜,于是看了別人是怎么做的。首先將數(shù)組排序,然后固定一個數(shù),用兩個指針指向該數(shù)右邊最大和最小的兩個數(shù),計算當前三個數(shù)的和,如果比0小則low指針右移,比0大則high指針左移,和0相等則記錄到答案中。記錄一次后要將low和high指針移動到下一個不相等的數(shù),避免重復記錄。寫出的代碼也很簡潔易懂:

# coding: utf-8
class Solution:
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        dic = {}
        res = []
        nums.sort()
        for i in range(len(nums)-2):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            low = i + 1
            high = len(nums) - 1
            while low < high:
                s = nums[i] + nums[low] + nums[high]
                if s < 0:
                    low += 1
                elif s > 0:
                    high -= 1
                else:
                    res.append([nums[i], nums[low], nums[high]])
                    while low < high and nums[low] == nums[low+1]:
                        low += 1
                    while low < high and nums[high] == nums[high-1]:
                        high -= 1
                    low += 1
                    high -= 1
        return res

代碼一次AC,時間復雜度還是O(n^2)。


#16. 3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

和上題差不多,要求變?yōu)榍蠼o出與目標數(shù)最接近的三個數(shù)的和。沿用上題的思路,很快就寫好了代碼:

# coding: utf-8
class Solution:
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        closest = 0
        minium = -1
        nums.sort()
        for i in range(len(nums)):
            low = i + 1
            high = len(nums) - 1
            while low < high:
                s = nums[i] + nums[low] + nums[high]
                d = abs(s - target)
                if d == 0:
                    return target
                if minium == -1 or d < minium:
                    minium = d
                    closest = s
                if s < target:
                    low += 1
                else:
                    high -= 1
        return closest

處理好邊界問題后代碼就AC了,時間復雜度還是O(n^2)。


#17. Letter Combinations of a Phone Number

Given a digit string, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below.

image

Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

給出幾個數(shù)字,要求給出數(shù)字對應的字母最多能組合的字符串。這是一個經(jīng)典的backtracking(回溯算法)的題目。當一個題目,存在各種滿足條件的組合,并且需要把它們全部列出來時,就可以考慮backtracking了。一開始想得沒有思路,看了提示用隊列解決。于是設計了一個隊列,對于每個輸入的數(shù)字,當隊列中有元素的長度小于當前的處理的數(shù)字個數(shù)時,取出該元素,然后在隊尾中分別加入該元素分別和當前數(shù)字對應的所有字母組成的新串。根據(jù)這個思路寫出代碼:

# coding: utf-8
class Solution:
    numbers = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]

    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        queue = [""]
        if len(digits) == 0:
            return []
        for i, v in enumerate(digits):
            while len(queue[0]) == i:
                tmp = queue.pop(0)
                for s in self.numbers[int(v)]:
                    queue.append(tmp+s)
        return queue

代碼很短,時間復雜度是O(n),基本上是一個枚舉算法。

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

推薦閱讀更多精彩內容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,392評論 0 10
  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,712評論 0 23
  • 華燈初上,侶人雙雙。獨孤一人,浪蕩天涯,秋水望斷碧波塘。 九月微涼,單薄衣裳。獨孤一人,亭下神傷,風過撫醒菊花秧。
    盛陌安閱讀 360評論 1 0
  • 也是剛想起來,原來今天是我的生日。剛吃完飯,去買饅頭去晚了沒買到,所以煮了兩袋泡面,菜有點咸了。這都沒什么,最主要...
    時光如故人閱讀 441評論 0 0