(Datawhale组队学习)Leetcode面试篇-Task2

题目1 Leetcode33 搜索旋转排序数组

  描述:给定一个整数数组 nums,数组中值互不相同。给定的 nums 是经过升序排列后的又进行了「旋转」操作的。再给定一个整数 target

  要求:从 nums 中找到 target 所在位置,如果找到,则返回对应下标,找不到则返回 -1

  说明

  • 旋转操作:升序排列的数组 nums 在预先未知的第 k 个位置进行了右移操作,变成了 [nums[k]], nums[k+1], ... , nums[n-1], ... , nums[0], nums[1], ... , nums[k-1]

 

def findmins(A, left, right):
    index = right
    while left<right:
        index = (left+right)//2
        if A[index] > A[right]:
            left = index+1
        else:
            right = index
    return left

def binaryfind(A, left, right, target):
    while left<=right:
        index = (left+right)//2
        if A[index]==target:
            return index
        if A[index]<target:
            left = index+1
        else:
            right = index-1
    return -1

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        # 先找到最小值的坐标,然后再比对最小值和target的大小
        # 如果target比nums[len-1]大,则只在最小值左边找
        # 如果target比nums[len-1]小,则只在最小值右边找
        l_nums = len(nums)
        index = findmins(nums, 0, l_nums-1)
        if target>nums[l_nums-1]:
            return binaryfind(nums, 0, index-1, target)
        elif target<nums[l_nums-1]:
            return binaryfind(nums, index, l_nums-1, target)
        else:
            return l_nums-1
        

题目2 Leetcode162 寻找峰值 

  描述:给定一个整数数组 nums

  要求:找到峰值元素并返回其索引。必须实现时间复杂度为 �(log⁡�) 的算法来解决此问题。

  说明

 

class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        # 找峰值,峰值两边的数都比它小,而非峰值的右边数一定比它大
        # 如果mid左小右小则输出mid
        # 如果mid右大左小则说明处在升序中,左侧可以抛弃
        # 如果mid右大左大则说明处在谷底,左右侧可以择一抛弃
        # 如果mid右小左大则说明处在降序,右侧可以抛弃
        # 综上,右边小的情况下,抛弃右边,右边大的情况下,抛弃左边
        left = 0
        right = len(nums)-1
        ans = 0 # 答案先默认是0
        def get_mid(index,A):
            if index == -1 or index == len(A):
                return float('-inf')
            return  A[index]
        while left<=right:
            mid = (left+right)//2
            if get_mid(mid-1,nums)<get_mid(mid,nums) and get_mid(mid,nums)>get_mid(mid+1,nums):
                ans = mid
                break
            if get_mid(mid,nums)>get_mid(mid+1,nums): # 右边小
                right = mid-1
            elif get_mid(mid,nums)<get_mid(mid+1,nums): # 右边大
                left = mid+1
        return ans

题目3 Leetcode04 寻找两个正序数组的中位数 

  描述:给定两个正序(从小到大排序)数组 nums1nums2

  要求:找出并返回这两个正序数组的中位数。

        这题写到最后都是云里雾里,靠着题解艰难copy完的,三天后重做一次。 

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        # 分两种情况 1.合并后长度为奇数 2.合并后长度为偶数
        # 奇数情况下,中位数就是最中间的那个数;偶数情况下,中位数是中间的两个数除以2
        # 思路:将A数组从i=(left+right)//2处分成两份,B数组从j=(n+m+1)//2-i处分开
        # A数组和B数组分成的两份A_1+B_1和A_2+B_2各自相加后,长度是相等的 
        # 找中位数就是找A_1+B_1的max值和A_2+B_2的min值
        # 如果max<=min且m+n为偶数,则这两个数除以2就是中位数,m+n为奇数则中位数是max
        # 如果max>min,则说明这样划分会使左边的数组过大,更新right=mid-1
        if len(nums1)>len(nums2): # 保证nums2是更长的列表
            return self.findMedianSortedArrays(nums2, nums1)

        l_1, l_2 = len(nums1), len(nums2)
        Inf = 2**40
        left, right = 0, l_1
        mid1, mid2 = 0, 0

        while left<=right:
            # 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]
            # 后一部分包含 nums1[i .. l_1-1] 和 nums2[j .. l_2-1]
            i = (left + right)//2
            j = (l_1 + l_2 + 1)//2 - i

            # nums_imax, nums_i, nums_jmin, nums_j 
            # 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]
            nums_imax = (-Inf if i == 0 else nums1[i - 1])
            nums_i = (Inf if i == l_1 else nums1[i])
            nums_jmin = (-Inf if j == 0 else nums2[j - 1])
            nums_j = (Inf if j == l_2 else nums2[j])

            if nums_imax <= nums_j:
                mid1, mid2 = max(nums_imax, nums_jmin), min(nums_i, nums_j)
                left = i + 1
            else:
                right = i - 1
            
        return mid1 if (l_1 + l_2)%2 else (mid1 + mid2)/2

        

题目4 Leetcode240 搜索二维矩阵 II

  描述:给定一个 �×� 大小的有序整数矩阵 matrixmatrix 中的每行元素从左到右升序排列,每列元素从上到下升序排列。再给定一个目标值 target

  要求:判断矩阵中是否可以找到 target,如果可以找到 target,返回 True,否则返回 False

 

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        # 就这个数据规模,遍历都遍历完了
        # 对每一行做一次二分查找吧
        def binaryfind(A, left, right, target):
            while left<=right:
                mid = (left+right)//2
                if A[mid]==target:
                    return True
                elif A[mid]>target:
                    right = mid-1
                else:
                    left = mid+1
            return False
        for x in matrix:
            if binaryfind(x, 0, len(x)-1, target):
                return True
        return False

题目5 Leetcode 69 x 的平方根 

  题目要求不使用内置函数,求出x的平方根,并且向下取整。

  很明显我们可以从0到x+1遍历,找到满足条件后的值后直接输出。

class Solution:
    def mySqrt(self, x: int) -> int:
        if x==1 or x==0:
            return x
        for i in range(0,x+1):
            if i*i == x:
                return i
            elif i*i > x:
                return i-1
        

  但是这题还是可以用二分查找的算法的,用正常遍历的思想,时间复杂度是O(n)级别的,换成O(logn)的二分查找明显 明显 

class Solution:
    def mySqrt(self, x: int) -> int:
        left = 0
        right = x+1
        while left<right:
            mid = (left+right)//2
            if mid*mid == x:
                return mid
            elif mid*mid > x:
                right = mid-1
            else:
                left = mid+1
        return left-1 if left**2 > x else left
        

题目6 Leetcode283 移动零

  描述:给定一个数组 nums

  要求:将所有 0 移动到末尾,并保持原有的非 0 数字的相对顺序。

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        lenth = len(nums)
        i = 0
        while i < lenth:
            if nums[i]==0:
                nums.pop(i)
                lenth -= 1
                nums.append(0)
                i -= 1
            i += 1

题目7 Leetcode415 字符串相加 

  描述:给定两个字符串形式的非负整数 num1 和num2

  要求:计算它们的和,并同样以字符串形式返回。

class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        # 先把长的数字放到num1中
        if len(num2)>len(num1):
            return self.addStrings(num2,num1)
        l_1 = len(num1)-1
        l_2 = len(num2)-1
        # 先对末尾进行加减
        jin = (int(num1[l_1]) + int(num2[l_2])) // 10
        num = (int(num1[l_1]) + int(num2[l_2])) % 10
        num1 = num1[:l_1] + str(num)
        l_1 -= 1
        l_2 -= 1
        while l_2>=0 or jin:
            if l_2>=0:
                num = (int(num1[l_1]) + int(num2[l_2]) + jin) % 10
                jin = (int(num1[l_1]) + int(num2[l_2]) + jin) // 10
                num1 = num1[:l_1] + str(num) + num1[l_1+1:]
            elif l_1>=0 and jin:
                num = (int(num1[l_1]) + jin) % 10
                jin = (int(num1[l_1]) + jin) // 10
                num1 = num1[:l_1] + str(num) + num1[l_1+1:]
            elif l_1<0 and jin:
                num1 = str(jin) + num1[:]
                jin = 0
            l_1 -= 1
            l_2 -= 1
        return num1

题目8 Leetcode239 滑动窗口最大值

  描述:给定一个整数数组 nums,再给定一个整数 k,表示为大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。我们只能看到滑动窗口内的 k 个数字,滑动窗口每次只能向右移动一位。

  要求:返回滑动窗口中的最大值。

 

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        ans = []
        # 设置一个list temp
        # temp最开始装着第一个区间内最大元素的下标
        # 后面开始滑动区间,每滑动一个元素,就用该元素和temp末尾的元素对比
        # 删去temp中比该元素小的的元素后,将该元素插入temp末尾,并删除已经脱离区间的元素
        temp = []
        for i in range(k):
            while temp and nums[i]>=nums[temp[-1]]:
                temp.pop()
            temp.append(i)
        ans.append(nums[temp[0]])
        for i in range(k,len(nums)):
            while temp and nums[i]>=nums[temp[-1]]:
                temp.pop()
            temp.append(i)
            while temp[0]<i-k+1:
                temp.pop(0)
            ans.append(nums[temp[0]])
        return ans

题目9 Leetcode03 无重复字符的最长子串

  描述:给定一个字符串 s

  要求:找出其中不含有重复字符的最长子串的长度。

 

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        son = ''
        l = 0
        for x in s:
            if x not in son:
                son += x
            else:
                while x in son:
                    son = son[1:]
                son += x
            l = max(l,len(son))
        return l

题目10 Leetcode76  最小覆盖子串

  描述:给定一个字符串 s、一个字符串 t

  要求:返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        # 如何匹配t是否是s的子串呢?
        # 建立两个字典,记录字符串中的的情况
        def check(dic_a, dic_b):
            for x in dic_b.keys():
                if x not in dic_a:
                    return False
                elif dic_a[x] < dic_b[x]:
                    return False
            return True

        son = ''
        temp = '' # 滑动窗口
        dic_s = {}
        dic_t = {}
        for x in t:
            if x in dic_t:
                dic_t[x] += 1
            else:
                dic_t[x] = 1
        for x in s:
            dic_s[x] = 0
        for x in s:
            temp += x
            dic_s[x] += 1
            if check(dic_s, dic_t):
                if son == '':
                    son = temp[:]
                while check(dic_s, dic_t):
                    if len(son) > len(temp):
                        son = temp[:]
                    dic_s[temp[0]] -= 1
                    temp = temp[1:]
        return son


题目11 Leetcode718 最长重复子数组 

  描述:给定两个整数数组 nums1nums2

  要求:计算两个数组中公共的、长度最长的子数组长度。

class Solution:
    def findLength(self, nums1: List[int], nums2: List[int]) -> int:
        l_1 = len(nums1)
        l_2 = len(nums2)
        d = [[0 for _ in range(l_2+1)] for _ in range(l_1+1)] # 状态矩阵初始全为0
        # d[i][j]是 以nums1[i]和nums2[j]结尾的元素最长子串长度
        # if nums1[i]==nums2[j]: d[i][j]=d[i-1][j-1]+1
        # else: d[i][j]=0
        ans = 0
        for i in range(1, l_1+1):
            for j in range(1, l_2+1):
                if nums1[i-1]==nums2[j-1]: # i-1和j-1都是为了fang
                    d[i][j] = d[i-1][j-1] + 1
                if d[i][j]>ans:
                    ans = d[i][j]
        return ans

题目12 Leetcode83 删除排序链表中的重复元素

  描述:给定一个已排序的链表的头 head

  要求:删除所有重复的元素,使每个元素只出现一次。返回已排序的链表。

 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        newhead = head
        if head==None or head.next==None: 
            return head

        while head and head.next : # 最后一个节点和空节点就不用考虑了
            while head.next and head.val == head.next.val: # 循环删除相同的值
                head.next = head.next.next
            head = head.next
            
        return newhead

题目13 Leetcode82 删除排序链表中的重复元素 II 

  描述:给定一个已排序的链表的头 head

  要求:删除原始链表中所有重复数字的节点,只留下不同的数字。返回已排序的链表。

 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        cur = ListNode(0)
        cur.next = head
        ans = cur
        while cur:
            now = cur.next
            flag = 0
            while now and now.next and now.val==now.next.val:
                now.next=now.next.next
                flag = 1
            if flag and not cur.next.next == None:
                cur.next = cur.next.next
            elif flag and cur.next.next == None:
                cur.next = None
            else:
                cur = cur.next
        return ans.next
            

 

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值