【劍指offer】剩餘題目彙總

個人感覺系列-_-||

順時針打印矩陣(頭條)

# -*- coding:utf-8 -*-
import numpy as np
class Solution:
    # matrix類型爲二維列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        res = []
        if not matrix: return res
        n = len(matrix) # n行
        m = len(matrix[0]) # m列
        # visted = # 記錄是否被訪問過
        # for i in range(m):
        #     aa.append(False)
        # print(aa)
        # for j in range(n):
        #     visted.append(aa)  # 這種初始化方式就是錯的
        visted = [[False for _ in range(m)] for _ in range(n)]
        # print(visted)
        x,y = 0,0 # 第一個點
        d = 1 # 初始方向是向右
        dx = [-1,0,1,0]
        dy = [0,1,0,-1]
        for i in range(n*m):
            res.append(matrix[x][y])
            visted[x][y] = True
            a = x + dx[d]
            b = y + dy[d]
            if a<0 or a>=n or b<0 or b>=m or visted[a][b]:
                # 撞牆啦! 就換方向
                d = (d+1)%4
                a = x + dx[d]
                b = y + dy[d]
            x, y = a, b
        return res



if __name__ == '__main__':
    matrix = [[1, 2, 3, 4],
              [5, 6, 7, 8],
              [9, 10, 11, 12],
              [13, 14, 15, 16]]
    print(Solution().printMatrix(matrix))

矩陣中的路徑

# -*- coding:utf-8 -*-
# leetcode79:單詞搜索
# newcoder上就是不通過
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        # write code here
        visited = [[False for _ in range(len(matrix[0]))] for _ in range(len(matrix))]
        for i in range(rows):
            # print()
            for j in range(cols):
                if self.dfs(matrix,path,i,j,0,visited):
                    # print("bbb")
                    return True
        return False

    def dfs(self,matrix,path,a,b,u,visited):
        # print("path",len(path))
        # print("u",u)
        # print("m:",matrix[a][b])
        # print("path",path[u])
        # print(matrix[a][b] == path[u])
        if matrix[a][b] != path[u]: return False
        if len(path) == u+1:return True
        dx = [-1,0,1,0]
        dy = [0,1,0,-1]
        for i in range(4):
            visited[a][b] = True
            x = a+dx[i]
            y = b+dy[i]
            if x>=0 and x<len(matrix) and y>=0 and y<len(matrix[0]) and not visited[x][y]:
                # print("yes")
                if self.dfs(matrix,path,x,y,u+1,visited):return True
        # print("q")
        visited[a][b] = False
        # print("a")
        return False

if __name__ == '__main__':
    matrix = [["a","b","c","e"],
              ['s','f','c','s'],
              ['a','d','e','e']]
    matrix = [["a"]]
    matrix = [["A",'B','C',"E"],
              ["S",'F','C',"S"],
              ["A",'D','E',"E"]]
    # print(matrix[2][3])
    # matrix[2][3] = "@"
    # print(matrix)
    # lucky = "abc"
    # lucky[1]="!"
    # print(lucky)
    # lucky[1]="!"
    # TypeError: 'str' object does not support item assignment
    row = 1
    col = 1
    row=3
    col=4
    path = "bcced"
    path = "abcb"
    path = "b"
    path = "ABCCED"
    print(Solution().hasPath(matrix,row,col,path))

機器人的運動範圍

# -*- coding:utf-8 -*-
# 寬度優先遍歷
class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        cnt = 0
        if not rows or not cols:return cnt
        visited = [[False for _ in range(cols)] for _ in range(rows)]
        # print(visited)
        queue = []
        queue.append([0,0]) # 從起點開始
        dx = [-1,0,1,0]
        dy = [0,1,0,-1]
        while queue:
            tmp = queue[0]
            # print(tmp)
            queue.pop(0)
            if self.get_sum(tmp)>threshold or visited[tmp[0]][tmp[1]]:continue
            cnt += 1
            visited[tmp[0]][tmp[1]] = True
            for i in range(4):
                x = tmp[0]+dx[i]
                y = tmp[1]+dy[i]
                if x>=0 and x<rows and y>=0 and y<cols:
                    queue.append([x,y])
        return cnt

    def get_single_sum(self,x):
        s = 0
        while x:
            s += x%10
            x //= 10
        return s

    def get_sum(self,pair):
        return self.get_single_sum(pair[0])+ \
               self.get_single_sum(pair[1])

if __name__ == '__main__':
    threshold = 7
    rows = 4
    cols = 5
    # print(Solution().get_single_sum(12))
    print(Solution().movingCount(threshold,rows,cols))

構建乘積數組

class Solution:
    def multiply(self, A):
        B = []
        if not A:return B
        n = len(A)
        p = 1
        for i in range(n):
            B.append(p)
            p *= A[i]
            # print(i,A[i])
        # print(B) # [1, 1, 2, 6, 24]
        p = 1
        for i in range(n-1,-1,-1):
            print("B", B[i])
            B[i] *= p
            p *= A[i]
        return B

字符串的全排列

# -*- coding:utf-8 -*-
class Solution:
    def Permutation(self, ss):
        # write code here
        if len(ss) <= 0:
            return []
        res = list()
        self.perm(ss, res, '')
        uniq = list(set(res))
        return sorted(uniq)
    # 從子串中挑一個字符,插入新的字符

    def perm(self, ss, res, path):
        if ss == '':
            res.append(path)
        else:
            for i in range(len(ss)):
                self.perm(ss[:i]+ss[i+1:], res, path+ss[i])

逆序數

class Solution:
    def InversePairs(self, data):
        # 採用歸併排序的思想,時間複雜度爲O(nlogn)
        global count
        count = 0
        def merge(array):
            global count
            if len(array) <= 1:
                return array
            k = len(array)//2
            left = merge(array[:k])
            right = merge(array[k:])
            l = 0
            r = 0
            result = []
            while l<len(left) and r<len(right):
                if left[l]<=right[r]:
                    result.append(left[l])
                    l+=1
                else:
                    result.append(right[r])
                    r += 1
                    count += len(left)+1
            result += left[l:]
            result += right[r:]
            return result
        merge(data)
        return count%1000000007


if __name__ == '__main__':
    data = [1,2,3,4,5,6,7,0]
    print(Solution().InversePairs(data))

滑動窗口最大值

from collections import deque
# 主要思想是:
# 每次比末尾元素大的纔可以入隊列
class Solution:
    def maxInWindows(self, num, size):
        # write code here
        res = []
        if not size or not num: return res
        # 可在兩端進行插入和刪除
        q = deque()
        # 隊列存在的是下標,不是數值
        for i in range(len(num)):
            # 如果超出滑動窗口,那麼把隊首元素踢掉,雙端隊列是不排序的
            while q and q[0] <= i-size:
                q.popleft()
            # 優勝劣汰,弱的出去,強的進來
            # 如果當前元素大於隊尾元素,入隊
            while q and num[i] >= num[q[-1]]:
                q.pop()
            q.append(i)
            # 返回結果
            if i >= size-1:
                res.append(num[q[0]])
        return res

two sum系列

兩數之和(hashtable)

# 要求時間複雜度O(N)
# Python solution using hash
class Solution(object):
    def twoSum(self, nums, target):
        if len(nums) <= 1:
            return False
        buff_dict = {}
        for i in range(len(nums)):
            if nums[i] in buff_dict:
                return [buff_dict[nums[i]], i]
            else:
                buff_dict[target - nums[i]] = i

和爲S的兩個數字

class Solution:
    # 如果有多對數字的和等於S,輸出兩個數的乘積最小的
    def FindNumbersWithSum(self, array, tsum):
        hashmap = {}
        rs = []
        minval = 2**31
        if not array:return rs
        if len(array)<=1: return rs
        for i in range(len(array)):
            # 在hashmap中
            if array[i] in hashmap:
                if array[hashmap[array[i]]]*array[i]<minval:
                    minval = array[hashmap[array[i]]]*array[i]
                    rs.append([array[hashmap[array[i]]],array[i]])
            # 不在hashmap中
            else:
                hashmap[tsum-array[i]] = i
        print(rs)
        if rs:return rs[-1]
        return rs

和爲S的連續正數序列

# 雙指針
class Solution:
    def FindContinuousSequence(self, tsum):
        s,j = 1,1
        res = []
        for i in range(1,tsum+1):
            while s<tsum:
                j += 1
                s += j
            if s==tsum and j-i+1>1:
                item = []
                for k in range(i,j+1):
                    item.append(k)
                res.append(item[:])
            s -= i
        return res

二分系列

不修改數組找出重複的數字

class Solution:
    def findDuplicate(self, nums):
        l = 1
        r = len(nums)-1
        while l<r:
            mid = l+r>>1
            sum = 0
            for x in nums:
                if x>=1 and x<=mid:sum+=1
            if sum>mid:r=mid
            else:l=mid+1
        return r
    
if __name__ == '__main__':
    nums = [1,3,4,2,2]
    print(Solution().findDuplicate(nums))

旋轉數組最小值

class Solution:
    def findMin(self, nums: List[int]) -> int:
        if not nums:return 0
        l=0
        r=len(nums)-1
        while l<r:
            mid = l+r>>1
            if nums[mid]<=nums[-1]:r=mid
            else:l=mid+1
        return nums[r]

旋轉數組找那個數字

 

0到n-1中缺失的數字

 

數字在排序數組中出現的次數

 

字符串相關

判斷字符串是否表示數值

# -*- coding:utf-8 -*-
class Solution:
    # E,e前後都要有東西
    # 小數點只能出現一次
    # +,-只能出現在s[0]或是e,E的後面
    def isNumeric(self, s):
        # write code here
        s = s.replace(" ","")
        if not s or (s[0]=='.' and len(s)==1):return False
        if s.count('.')>1 or s.count('e')>1 or s.count('E')>1 \
                or s.count('+')>2 or s.count('-')>2:return False

        if s[0] in '+-':s=s[1:]
        dot, e = 0, 0
        i, n = 0, len(s)
        while i < n:
            if s[i]=='.' and e:
                return False
            elif s[i]=='e' or s[i]=='E':
                e += 1
                if i==0 or i == n-1:
                    return False
                if s[i+1]=='+' or s[i+1]=='-':
                    if i+2==n:
                        # print(i+2)
                        # print(i, s[i])
                        return False
                    i += 1
            elif s[i]!='.' and s[i] not in "0123456789":
                return False
            i += 1
        return True


"""
定義兩個標誌位,分別表示E或者e是否出現過,以及小數點.是否出現過。 
1. 以e(或E)爲分隔,獲得兩個子字符串;e之前的字符串小數點只能出現一次;e之後的字符串不允許出現小數點; 
2. 符號位+或-只可能出現在兩個子字符串的首位; 
3. e(或E)、小數點.不能出現在末尾
"""

if __name__ == '__main__':
    # s = "-1E-16 "
    s = " 1a3.14"
    s = "123.45e+6"
    print(Solution().isNumeric(s))

把字符串轉成整數

# -*- coding:utf-8 -*-
class Solution:
    def StrToInt(self, s):
        if not s:return 0
        k = 0
        while k<len(s) and s[k]==' ':k+=1
        num = 0
        is_minus = False
        if s[k] == '+': k += 1
        elif s[k] == '-':
            k += 1
            is_minus = True
        while k<len(s) and s[k]>='0' and s[k]<='9':
            # num = num*10+(ord(s[k])-48)
            num = num*10+(ord(s[k])-ord('0'))
            k+=1
        if k!=len(s):return 0
        if is_minus:
            num *= -1
        return num

if __name__ == '__main__':
    s = '1a33'
    print(Solution().StrToInt(s))

動態規劃

把數字翻譯成字符串(leetcode91)

# 實際上有兩個約束條件,1. 0不能單獨解碼 2. 兩位數必須在1與26之間。
# 這道題目實際上是用DP去做,仔細想的話,可以發現就是約束版的f(n) = f(n-1) + f(n-2);
# 其中如果是s[n-1]爲0,f(n-1) = 0,f(n) = f(n-2),
# 因爲0無法單獨解碼,而f(n-2)的條件則是必須在1與26之間,否則f(n) = f(n-1)。
class Solution:
    def numDecodings(self, s):
        if s == "" or s[0]=='0': return 0
        dp=[1,1]
        for i in range(2,len(s)+1):
            if 10 <=int(s[i-2:i]) <=26 and s[i-1]!='0':#編碼方式爲2
                dp.append(dp[i-1]+dp[i-2])
            elif int(s[i-2:i])==10 or int(s[i-2:i])==20:#編碼方式爲1
                dp.append(dp[i-2])
            elif s[i-1]!='0':#編碼方式爲0
                dp.append(dp[i-1])
            else:
                return 0
        #print(dp[len(s)])
        return dp[len(s)]
    
if __name__ == "__main__":
    s = "12"
    print(Solution().numDecodings(s))
        
"""
s[i-2]和s[i-1] 兩個字符是10----26之間但不包括10和20這兩個數時,有兩種編碼方式,比如23------>[“BC”,“W”],所以dp[i] = dp[i-1]+dp[i-2]

s[i-2]和s[i-1] 兩個字符10或20這兩個數時,有一種編碼方式,比如10------>[“J”], 所以dp[i] = dp[i-2]

s[i-2]和s[i-1] 兩個字符不在上述兩種範圍時,編碼方式爲零,比如27,比如01,所以dp[i] = dp[i-1
"""

Python庫的使用

把數組排成最小的數

# -*- coding:utf-8 -*-
import functools
# https://blog.csdn.net/u012436149/article/details/79952975
class Solution:
    def helper(self,a,b):
        # a<b一定有ab<ba
        ab = int(a + b)
        ba = int(b + a)
        return 1 if ab > ba else -1

    def PrintMinNumber(self, numbers):
        numbers = [str(num) for num in numbers]
        numbers = sorted(numbers,key=functools.cmp_to_key(self.helper))
        print(numbers)
        return "".join(numbers)

if __name__ == '__main__':
    n = [32,3,321]
    print(Solution().PrintMinNumber(n))
    # 321323

 

看到別人考過的leetcode上的題目

leetcode5

# 馬拉車算法——Manacher 算法 
# 現將字符串通過添加特定字符'#',變成奇數個數。對新字符串使用中心擴展發即可,中心擴展法得到的半徑就是子串的長度。
# 先轉化字符串'35534321'  ---->  '#3#5#5#3#4#3#2#1#',然後求出以每個元素爲中心的最長迴文子串的長度。

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # manacher 算法
        s = '#' + '#'.join('{}'.format(s)) + '#'
        lens=len(s)
        max_str = ""
        max_length = 0
        for i in range(lens):
            cur_length,cur_str = self.getLength(s,i)
            if cur_length>max_length:
                max_length = cur_length
                max_str = cur_str
        return max_str.replace('#','')

    def getLength(self,s,index):
        length = 0
        string = s[index]
        for i in range(1,index+1):
            # 從index開始的原因是:從當前詞開始向兩邊擴散
            if i+index<len(s) and s[index-i]==s[index+i]:
                length+=1
                string = s[index-i:index+i]
            else:
                break
        return length,string

 

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