【Leetcode】技巧系列

 【Leetcode-6】

一、题目:Z字形变换

  将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

  

二、代码:

def convert(self, s: str, numRows: int) -> str:
        """
        设置n个list,一个个往里填,行到0或者n-1就转方向,空的位置不管
        """
        res = [''] * numRows
        direction = 1  # 代表向下,行+1
        r = 0  # 当前处在第0行
        for item in s:
            res[r] += item
            r = r+1 if direction > 0 else r-1  # 下一步要走的行
            if r == numRows or r < 0:  # 行超出边界
                r = r-2 if r == numRows else r+2  # 退2步或进2步
                direction = -direction  # 换方向
        res = ''.join(res)
        return res

 

【Leetcode-26】

一、题目:删除有序数组中的重复项

  给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

  不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

二、代码:

def removeDuplicates(self, nums: List[int]) -> int:
        """
        两个指针,一个指向处理完的位置,一个指向待处理的位置,若待处理的值和处理完的不相同则复制过来,处理完指针后移,返回处理完指针的位置
        """
        if len(nums) == 0:
            return 0 
        p = 0
        for i, item in enumerate(nums):
            if item != nums[p]:
                p += 1
                nums[p] = item
        return p+1  # 数组长度为指向位置+1

 

【Leetcode-27】

一、题目:移除元素

  给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

  不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

  元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

二、代码:

def removeElement(self, nums: List[int], val: int) -> int:
        p = -1  # 处理完的下标
        for i in range(len(nums)):
            if val != nums[i]:
                p += 1
                nums[p] = nums[i]
        return p+1

 

【Leetcode-54】

一、题目:螺旋矩阵

  给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

二、代码:

def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        """
        遍历过或者超出边界的为墙,撞墙则转方向,否则朝当前方向走,进来的地方为(0,-1)
        """
        m, n = len(matrix), len(matrix[0])
        directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        dir_idx = 0  # 当前方向
        x, y = 0, -1  # 当前所处位置
        res = []
        visited = set()
        for _ in range(m*n):  # 所有数
            direction = directions[dir_idx]
            new_x, new_y = x + direction[0], y + direction[1]
            if not (0<=new_x<m and 0<=new_y<n and (new_x, new_y) not in visited):
                # 撞墙或者已经遍历
                dir_idx = (dir_idx+1) % len(directions)
                direction = directions[dir_idx]
                new_x, new_y = x + direction[0], y + direction[1]
            visited.add((new_x, new_y))
            res.append(matrix[new_x][new_y])
            x, y = new_x, new_y
        return res

 

【Leetcode-56】

一、题目:合并区间

  以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。

二、代码:

 def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        res = []
        if len(intervals) == 0:
            return res

        intervals.sort(key=lambda x: x[0])
        p = intervals[0]
        for item in intervals[1:]:
            if item[0] <= p[1]:
                p = [min(p[0], item[0]), max(p[1], item[1])]
            else:
                res.append(p)
                p = item
        res.append(p)
        return res

 

【Leetcode-88】

一、题目:合并两个有序数组

  

二、代码:

def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        逆向双指针,避免额外空间,每次选最大的填入尾部
        """
        p = m + n - 1 # 最终结果指针
        p1 = m - 1
        p2 = n - 1
        while p >= 0:
            val1 = nums1[p1] if p1 >= 0 else float('-inf')
            val2 = nums2[p2] if p2 >= 0 else float('-inf')
            if val1 > val2:
                nums1[p] = val1
                p1 -= 1
            else:
                nums1[p] = val2
                p2 -= 1
            p -= 1

 

【Leetcode-128】

一、题目:最长连续序列

  

二、代码:  

def longestConsecutive(self, nums: List[int]) -> int:
        look_up = {}
        for item in nums:
            look_up[item] = 1
        max_len = 0
        for item in nums:
            if item-1 not in look_up:
                this_len = 1
                while item + 1 in  look_up:
                    this_len += 1
                    item += 1
                max_len = max(max_len, this_len)
        return max_len

 

【Leetcode-169】

一、题目:多数元素

  给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

  你可以假设数组是非空的,并且给定的数组总是存在多数元素。

二、代码:

ef majorityElement(self, nums: List[int]) -> int:
        major = nums[0]
        count = 1
        for item in nums[1:]:
            if item == major:
                count += 1
            else:
                count -= 1
            if count == 0:
                major = item
                count = 1
        return major

 

【Leetcode-238】

一、题目:除自身以外的乘积

  给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

二、代码:

def productExceptSelf(self, nums: List[int]) -> List[int]:
        n = len(nums)
        output = [1]*n
        # 计算每个位置左边的乘积
        for i in range(1, n):
            output[i] = nums[i-1] * output[i-1]
        # 累乘右边的乘积
        right_val = 1
        for i in reversed(range(n)):
            output[i] = output[i] * right_val
            right_val = nums[i] * right_val
        return output

 

【Leetcode-280】

一、题目:摆动排序

  给你一个无序的数组 nums, 将该数字 原地 重排后使得 nums[0] <= nums[1] >= nums[2] <= nums[3]...。答案不唯一。

二、代码:

def wiggleSort(self, nums: List[int]) -> None:
        """
        逐位与前一位比较,不对则对换,一次大一次小
        """
        n = len(nums)
        if n <= 1:
            return nums
        flag = 1  # 要求比前面的大,也可以等于
        for i in range(1, n):
            if flag > 0:
                if nums[i] < nums[i-1]:
                    nums[i], nums[i-1] = nums[i-1], nums[i]
            else:  # 要求比前面的小,也可以等于
                if nums[i] > nums[i-1]:
                    nums[i], nums[i-1] = nums[i-1], nums[i]
            flag = -flag
        return nums

 

【Leetcode-283】

一、题目:移动零

  给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

二、代码:

def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        """
        p指向已处理完序列的尾部,尾部向后扩展,遇到的字符不是0则调换到前面
        """
        p = 0
        for i in range(len(nums)):
            # if i == 0:
            #     continue
            if nums[i] != 0:
                nums[p], nums[i] = nums[i], nums[p]
                p += 1

 

【Leetcode-383】

一、题目:赎金信

  给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。

  (题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)

二、代码:

def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        """
        a中出现频率<b中出现频率
        """
        def get_cnt(s):
            res = dict()
            for item in s:
                cnt = res.get(item, 0)
                res[item] = cnt + 1
            return res
        cnt1 = get_cnt(ransomNote)
        cnt2 = get_cnt(magazine)
        for k, n1 in cnt1.items():
            n2 = cnt2.get(k, 0)
            if n1 > n2:
                return False
        return True

 

【Leetcode-406】

一、题目:根据身高重建队列

  假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。

  请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

二、代码:

def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
        """
        先按身高排序,再插队
        """
        people.sort(key=lambda x: (-x[0], x[1]))
        res = []  # 已经排好队的人
        for item in people:
            if len(res) > item[1]:
                res.insert(item[1], item)
            else:
                res.append(item)
        return res

 

【Leetcode-448】

一、题目:找到所有数组中消失的数字

  

二、代码:

def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
        n = len(nums)
        res = []
        for i in range(n):
            nums[i] -= 1
        for item in nums:
            nums[item % n] += n
        for i, item in enumerate(nums):
            if item < n:
                res.append(i+1)
        return res

 

【Leetcode-581】

一、题目:最短无序连续子数组

  给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。

  请你找出符合题意的 最短 子数组,并输出它的长度。

二、代码:

def findUnsortedSubarray(self, nums: List[int]) -> int:
        nums_new = sorted(nums)
        n = len(nums_new)
        start, end = -1, n
        for i in range(n):
            if nums[i] != nums_new[i]:
                end = i
            if nums[n-i-1] != nums_new[n-i-1]:
                start = n-i-1
        if start == -1:
            return 0
        else:
            return end-start+1

 

【Leetcode-621】

一、题目:任务调度器

  

二、代码:

def leastInterval(self, tasks: List[str], n: int) -> int:
        """
        最重复的任务的次数为k,设置k个桶,相同任务不能放入同一桶,即可满足要求,求桶里任务量(空闲也算任务),桶的大小为n+1,即每个桶执行完任务就填入冷却任务(此时也算执行其他任务)。但当冷却时间较小时,需要扩大桶的容量,导致每个桶都被填满,此时需要的时间为任务数。因此最终时间选择最大值。
        """
        from collections import Counter
        cnt = Counter(tasks)
        cnt_list = list(cnt.values())
        k = max(cnt_list)
        # 前k-1个桶都装满,消耗的时间
        t1 = (k-1)*(n+1)
        # 最后一个桶不一定装满,装的数为数量为k的任务个数
        t2 = len([t for t in cnt_list if t==k])
        return t1+t2 if t1+t2 > len(tasks) else len(tasks)

 

posted @ 2021-04-01 22:39  我若成风者  阅读(93)  评论(0编辑  收藏  举报