leetcode 第一周题解 (2.167.215.347.75.455)

本文深入讲解了多种高效算法,包括最长不重复子串、两数之和、快速选择与堆排序、桶排序前K个高频词等核心算法的实现与优化,通过实例演示如何运用这些算法解决实际问题。

2. 最大不重复字段判断

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        #因为是 ASCII码值,可以使用 256长度的 list 代表ascii码值
        index_list = [-1 for i in range(256)]
        #也可以直接使用字典
        #index_map = {}
        start = -1
        maxLen = 0
        str_len = len(s)
        for j in range(str_len):
            charac = s[j]
            if index_list[ord(charac)] > start:
                start = index_list[ord(charac)]

            index_map[ord(charac)]=j
            maxLen = max(maxLen,j-start)      
        
        return maxLen
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        #也可以直接使用字典
        index_map = {}

        start = -1
        maxLen = 0
        str_len = len(s)
        for j in range(str_len):
            charac = s[j]
            if index_map.get(charac) > start:
                start = index_map.get(charac)

            index_map[charac]=j
            maxLen = max(maxLen,j-start)      
        
        return maxLen

167. 两数之和

时间复杂度最大 是 O(2n) 最好成绩 36ms

首先遍历一次numbers 列表。 把每一个元素和它所对应的位置 用一个 字典存储 key :元素值 ,value:index+1。

遍历中用 和减去每一个数,如果小于0的结果舍去。 大于等于0的结果存入存入List 第一个元素差,第一个元素index+1。

然后遍历这个得到的结果List 取每一个值,跟字典的keys比较。看有没有,有的取出结果,排序后返回。

如果numbers 不是升序排列,双指针不适用。这个方法比较好。

class Solution(object):
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        dict_num = {}
        list_2 = []
        for i in range(len(numbers)):
            dict_num[numbers[i]] = i+1
            diff = target - numbers[i]
            if diff >= 0:
                list_2.append([diff ,i+1])
        for m in list_2:
            if dict_num.get(m[0]) != None:
                res = sorted([dict_num.get(m[0]),m[1]])
                return res 

改进版:

之前想可能在第一个循环判断 diff 是否在 dict_num 中如果 dict_num 还没有加入会漏掉结果。但是后来大神代码和自己根据思考得到,因为两个加数都在这个列表之内,漏掉了第一个加数后,第二个加数判断绝对不会漏掉。代码如下 时间复杂度为 O(n)

class Solution(object):
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        dict_num = {}
        list_2 = []
        for i in range(len(numbers)):            
            diff = target - numbers[i]
            if diff in dict_num:
                return [dict_num[diff]+1 ,i+1]
            dict_num[numbers[i]] = i

双指针

最大时间复杂度 O(n), 最优用时28ms 。利用了numbers 正排序规则。

从开始有一个指针 从头到尾, 末尾一个指针从尾向头进行搜索。 当末尾指针与头指针重合的时候说明整个数据列表遍历完成。所以需要末尾指针 index 大于 头指针index,当等于结果的时候返回 所在index+1。 如果两指针指向的结果大于目标值,说明两数和较大,减小较大的一个加数。 小了,说明两数和较小,增大较小的一个加数。

class Solution(object):
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        if len(numbers) < 2:
            return False
        index1 = 0
        index2 = len(numbers) - 1
        while index1 < index2:
            if numbers[index1] + numbers[index2] == target:
                return [index1+1,index2+1]
            else:
                if numbers[index1] + numbers[index2-1] >= target:
                    index2 -= 1
                else:
                    index1 += 1

215. 快速选择、堆排序

​ 利用堆排序进行计算。 计算方法

  • 将数字转化为一个堆;
    堆是具有以下两属性的二叉树:
    (1)每个节点的值大于等于其子节点的值;
    (2)树完全平衡,即最底层叶子节点都位于左侧(完全),且左右子树高度相差不超过1(平衡);

    堆也被称为优先队列,具有先进先出的特性,在堆底插入元素,在堆顶取出元素。

  • 取出堆顶元素(最大元素),作为有序数数组末尾元素,并对二叉树进行调整使其满足堆的特性;

  • 重复上一步骤,依次取出堆顶元素,并插入到有序数组中,上一插入元素之前的位置,直到堆空为止;

class Solution(object):
    
    def moveDown(self,arr,first,last):
        curIndex = first * 2 + 1
        while curIndex <= last:
            if curIndex < last and (arr[curIndex] < arr[curIndex +1]):
                curIndex += 1
            if arr[first] < arr[curIndex]:
                arr[first],arr[curIndex] = arr[curIndex],arr[first]
                first = curIndex
                curIndex = curIndex * 2 + 1
            else:
                break

    def buildHeap(self,arr):
        i = len(arr)//2 -1
        while i >=0:
            self.moveDown(arr, i ,len(arr) -1)
            i = i -1
           
    
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
     
        self.buildHeap(nums)
        
        first = 0
        last = len(nums) - 1
        k -= 1
        while k >0:
            nums[first],nums[last] = nums[last],nums[first]
            last -=1
            self.moveDown(nums, first, last)
            k -=1
        
        return nums[first]

347. 桶排序 前K个高频词

思路: 首先把 列表转化成 集合去重复。 然后加入字典为key , value是 0 。 遍历一次nums。得到各自个数。然后取 字典的 values 逆行排序, 然后根据头 k 个value,逆差找字典 找到key。返回结果。比较low ,速度很慢,但是绝对是原创。

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        num_set = set(nums)
        num_list = list(num_set)
        dict_1 = {}
        dict_1 = dict_1.fromkeys(num_list,0)
        for i in nums:
            dict_1[i] = int(dict_1.get(i)) + 1
        list_2 = sorted(list(dict_1.values()),reverse=True)
        list_3 = []
        for j in range(k):
            n_key = list(dict_1.keys())[list(dict_1.values()).index(list_2[j])]
            list_3.append(n_key)
            dict_1.pop(n_key)
        
        return list_3

75. 颜色分类

思路: 设置两个指针,头指针用于指向0 尾指针用于指向2。 然后从头开始对数组进行搜索,不用超过尾指针。因为尾指针会对2进行排列。 当遍历的索引 对应的数是0的时候,放到头指针对应位置,当前索引和头指针都加1。同理当前遍历的索引对应的数为2时候,放到尾指针对应位置,并且尾指针向前移动一格。

class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        #设置指零的头指针
        i = 0
        #设置指2的尾指针
        j = len(nums) - 1
        #遍历 从头到尾每个位置都经过。
        m = 0
        #总体思路,遍历索引不能大于尾指针。由于我们知道 0,1,2 的值。就可以类似判断 为0的往头放
        #为2的 往尾巴上面放。 索引直接增加的理念就行。
        while m <= j:
            if nums[m] == 0:
                nums[m],nums[i] = nums[i],nums[m]
                i +=1
                m +=1
            elif nums[m] == 2:
                nums[m],nums[j] = nums[j],nums[m]
                j -=1
            else:
                m +=1

455. 分发饼干

贪心算法的应用: 对孩子和 饼干都进行排序(ascend), 以饼干进行遍历。 孩子加一个头指针,如果饼干值不小于孩子值。数量加1,孩子头指针向后移动一格。 如果孩子遍历完成,或者饼干遍历完成结束循环。

class Solution(object):
    def findContentChildren(self, g, s):
        """
        :type g: List[int]
        :type s: List[int]
        :rtype: int
        """
        g = sorted(g)
        s = sorted(s)
        z = 0
        indx = 0
        for ele in s:
            if indx < len(g) and ele >= g[indx] :
                z += 1
                indx +=1
        
        return z
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值