剑指offer解题思路简述 41-50

  • 面试题41:数据流中的中位数

方法1:没有排序的数组,插入1,得到中位数n

方法2:排序的数组,插入n,得到中位数1

方法3:排序的链表,同排序的数组

方法4:最大堆+最小堆,插入logn,得到中位数1,保证建立的最大堆的每个数都小于最小堆,为保证两个堆平衡,个数为偶数的话,先放入到大根堆,然后将大根堆中最大的树插入到小根堆中;个数为奇数的话,先放入到小根堆,然后将小根堆中最小的树插入到大根堆中。当前个数为偶数个,则取小根堆和大根堆的堆顶元素求平均;个数为奇数的话直接从小根堆中取最小值。

  • 面试题42:连续子数组的最大和

方法:当前累加的和若为负数,直接舍弃,保存当前的最大和,从下一个数重新开始累加

class Solution:
    def FindGreatestSumOfSubArray(self, array):
        # write code here
        #遇到负和,抛弃之前的
        maxsum = max(array)
        temp = 0
        for i in array:
            if temp>=0:
                temp = temp +i
                maxsum = max(temp,maxsum)
            else:
                 temp =i
        return maxsum
  • 面试题43:1~n整数中1出现的次数

方法:有点绕,放弃

  • 面试题44:数字序列中某一位的数字

剑指offer解题思路简述 41-50_第1张图片

方法:将所有的数字分区间,1-9一共10个数,9位;10-99一共90个数,90*2位,100-999一共900个数,900*3。所以先确定给出的位数在哪个区间内,例如365:365-9-180 = 176<2700,所以是三位数,然后确定是哪个数中的位数,即176/3=58...2,所所求数是99+58之后那个数的第二位,即159的第二位5

class Solution:
    def findNthDigit(self, n: int) -> int:
        digit, start, count = 1, 1, 9
        while n > count: # 1.
            n -= count
            start *= 10
            digit += 1
            count = 9 * start * digit
        num = start + (n - 1) // digit # 2.
        return int(str(num)[(n - 1) % digit]) # 3.

  • 面试题45:把数组排成最小的数

方法一:求全排列,然后比较大小

方法二:各种排序方法皆可,只不过把比较大小大的方式换成字符串的拼接后比较

class Solution:
    def minNumber(self, nums: List[int]) -> str:
        def fast_sort(l , r):
            if l >= r: return
            i, j = l, r
            while i < j:
                while strs[j] + strs[l] >= strs[l] + strs[j] and i < j: j -= 1
                while strs[i] + strs[l] <= strs[l] + strs[i] and i < j: i += 1
                strs[i], strs[j] = strs[j], strs[i]
            strs[i], strs[l] = strs[l], strs[i]
            fast_sort(l, i - 1)
            fast_sort(i + 1, r)
        
        strs = [str(num) for num in nums]
        fast_sort(0, len(strs) - 1)
        return ''.join(strs)

方法三:

sorted(ss, key=functools.cmp_to_key(lambda a,b: int(str(a)+str(b))-int(str(b)+str(a))), reverse=True)
  • 面试题46:把数字翻译成字符串

剑指offer解题思路简述 41-50_第2张图片

方法:从后往前,相当于斐波拉契数列,只不过这里面多了一个条件,只有当10*s[-1-i]+s[-i]需要在小于25,f(n)=f(n-1)+f(n-2),如果大于的话f(n)=f(n-1)

class Solution:
    def translateNum(self, num):
        str_num = str(num)
        n = len(str_num)
        dp = [1 for _ in range(n + 1)] 
        for i in range(2, n + 1):
            if str_num[i - 2] == '1' or \
            (str_num[i - 2] == '2' and str_num[i - 1] < '6'):
                dp[i] = dp[i - 2] + dp[i - 1]
            else:
                dp[i] = dp[i - 1]
        return dp[n]
  • 面试题47:礼物的最大价值

剑指offer解题思路简述 41-50_第3张图片

方法:两层for循环,当第一行或者第一列的时候,只用当前值加上该行或者该列的上一个值就可以,其他的情况需要加上一行和上一列的最大值。优化的方法:在原数组上操作,不需要新建一个空间。

class Solution:
    def maxValue(self, grid: List[List[int]]) -> int:
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if i == 0 and j == 0: continue
                if i == 0: grid[i][j] += grid[i][j - 1]
                elif j == 0: grid[i][j] += grid[i - 1][j]
                else: grid[i][j] += max(grid[i][j - 1], grid[i - 1][j])
        return grid[-1][-1]
  • 面试题48:最长不含重复字符的子字符串

剑指offer解题思路简述 41-50_第4张图片

方法:遍历字符串,建一个等长的数组保存当前位置的最大字符串数,建一个list保存当前状态下前面不重复的字符串,每次遍历都更新,如果新来的字符没有重复,则直接加一,有重复的话找到在list中的位置,切片获取它后面的部分,然后更新

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        if len(s)<2:return len(s)
        temp = [s[0]]
        result = [1]
        for i in range(1,len(s)):
            if s[i] not in temp:
                result.append(result[i-1]+1)
                temp.append(s[i])
            else:
                index = temp.index(s[i])
                temp = temp[index+1:]
                temp.append(s[i])
                result.append( len(temp))

        return max(result)
  • 面试题49:丑数

剑指offer解题思路简述 41-50_第5张图片

方法:思路就是用2,3,5分别乘以找到的丑数,并且整个过程按照大小顺序排列。[1,2,3,....]设置三个初始值为0的数分别标记当前2,3,5乘到了结果list的第几位,如先比较1*2,1*3,1*5,明显2小,所以把2 append进list里,然后把2的标志位加1,下次2就需要乘2,再和其他比较。

class Solution:
    def GetUglyNumber_Solution(self, index):
        # write code here
        if index < 1:
            return 0       
        res = [1]
        t2 = t3 = t5 = 0    
        next = 1
        while next < index:
            min_num = min(res[t2]*2, res[t3]*3, res[t5]*5)
            res.append(min_num)
            #3个if为了防止出现同时出现两个相同的数的情况
            if res[t2]*2 <= min_num:
                t2 += 1
            if res[t3]*3 <= min_num:
                t3 += 1
            if res[t5]*5 <= min_num:
                t5 += 1
            next += 1
        return res[index-1]
  • 面试题50:第一个只出现一次的字符

剑指offer解题思路简述 41-50_第6张图片

方法1:创建一个哈希表,字符作为key,次数作为value,字符的种类一共有256个,所以空间复杂度为1。扫描两次字符串,第一次记录每个字符串出现的次数,第二次从前遍历,找到value值第一次出现为1的key,时间复杂度为n

class Solution:
    def firstUniqChar(self, s: str) -> str:
        dicts={}
        for i in s:
            dicts[i]=dicts.get(i,0)+1
        for i in s:
            if dicts[i]==1:
                return i
        return ' '

方法2:利用python自带的函数,for index, value in enumerate(s): if s.count(value) == 1:return 

python中可以放到set里,在set里查找一个元素的时间复杂度是1

剑指offer解题思路简述 41-50_第7张图片

方法:设置一个字典存放字符和次数,设置一个list存放当前出现过的字符,每次for list,找到第一个value值为1的key,直接返回

class Solution:
    # 返回对应char
    def __init__(self):
        self.l=[]
        self.d={}
    def FirstAppearingOnce(self):
        # write code here
        for char in self.l:
            if self.d[char]==1:
                return char
        return '#'
    def Insert(self, char):
        # write code here
        if char in self.d:
            self.d[char]+=1
        else:
            self.d[char]=1
        if self.d[char]==1:
            self.l.append(char)

 

你可能感兴趣的:(剑指offer解题思路简述 41-50)