victory的博客

长安一片月,万户捣衣声

0%

88.合并两个有序数组

题目描述

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

题目链接

思路

  1. 归并
    设置两个指针i,j,从头开始遍历两个数组,哪个指针指向位置的元素较小则加入结果列表中,该指针后移,…,依次类推。
    如果两个数组长度不一样,循环结束后,需要将长度较长的数组剩余元素加入结果列表。
  2. 双指针
    由于题目所给数组均有序,因此可以设置两个指针分别指向两个数组第一个元素,判断两个指针指向位置的元素大小,每次将较小的加入结果列表中。
    如果某一个数组先遍历结束,后续只需要遍历另一个数组的剩余元素并将其加入结果列表中。
  3. 先将数组nums2放进数组nums1的尾部,然后直接对整个数组进行排序
  4. 逆向双指针
    对双指针法进行改进,从后往前遍历数组,每次将较大元素放入结果列表中。
    在双指针法中,我们需要创建长度为m+n的新数组保存结果,因为如果直接在nums1上保存,会覆盖nums1的元素。
    与双指针方法不同的是,该方法可以原地地在nums1上保存结果(从后往前放入元素不会产生覆盖)。

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    class Solution(object):
    def merge(self, nums1, m, nums2, n):
    """
    归并
    :type nums1: List[int]
    :type m: int
    :type nums2: List[int]
    :type n: int
    :rtype: None Do not return anything, modify nums1 in-place instead.
    """
    i = 0
    j = 0
    result = []
    while i < m and j < n:
    if nums1[i] < nums2[j]:
    result.append(nums1[i])
    i += 1
    elif nums1[i] >= nums2[j]:
    result.append(nums2[j])
    j += 1

    if m - i != 0:
    for k in range(m - (m - i), m):
    result.append(nums1[k])
    if n - j != 0:
    for p in range(n - (n - j), n):
    result.append(nums2[p])

    nums1[:] = result

    def merge1(self, nums1, m, nums2, n):
    # 先将数组nums2放进数组nums1的尾部,然后直接对整个数组进行排序
    nums1[m:] = nums2
    quick_sort(nums1, 0, len(nums1) - 1)

    def merge2(self, nums1, m, nums2, n):
    sorted = []
    p1, p2 = 0, 0
    while p1 < m or p2 < n:
    if p1 == m:
    sorted.append(nums2[p2])
    p2 += 1
    elif p2 == n:
    sorted.append(nums1[p1])
    p1 += 1
    elif nums1[p1] < nums2[p2]:
    sorted.append(nums1[p1])
    p1 += 1
    else:
    sorted.append(nums2[p2])
    p2 += 1
    nums1[:] = sorted

    def merge3(self, nums1, m, nums2, n):
    """逆向双指针"""
    p1, p2 = m - 1, n - 1
    tail = m + n - 1
    while p1 >= 0 or p2 >= 0:
    if p1 == -1: # 如果nums1数组已经遍历完毕,遍历nums2中的剩余元素
    nums1[tail] = nums2[p2]
    p2 -= 1
    elif p2 == -1: # 如果nums2数组已经遍历完毕,遍历nums1中的剩余元素
    nums1[tail] = nums1[p1]
    p1 -= 1
    elif nums1[p1] > nums2[p2]:
    nums1[tail] = nums1[p1]
    p1 -= 1
    else:
    nums1[tail] = nums2[p2]
    p2 -= 1

    tail -= 1


    def quick_sort(arr, low, high):
    """快速排序"""
    if low < high:
    pivot = partition(arr, low, high)
    quick_sort(arr, low, pivot - 1)
    quick_sort(arr, pivot + 1, high)


    def partition(arr, low, high):
    pivot_key = arr[low]
    while low < high:
    while low < high and arr[high] >= pivot_key:
    high -= 1
    arr[low], arr[high] = arr[high], arr[low]
    while low < high and arr[low] <= pivot_key:
    low += 1
    arr[low], arr[high] = arr[high], arr[low]
    return low


    if __name__ == "__main__":
    slt = Solution()
    nums1 = [1, 2, 3, 0, 0, 0]
    nums2 = [2, 5, 6]
    # slt.merge(nums1, 3, nums2, 3)
    # slt.merge1(nums1, 3, nums2, 3)
    # slt.merge2(nums1, 3, nums2, 3)
    slt.merge3(nums1, 3, nums2, 3)
    print(nums1)

66.加一

题目描述

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。

题目链接

思路

  1. 从后往前找第一个不为9的元素,并将该位置后的9置零
  2. 将数组转化为数字加一再将结果转化为整数数组

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class Solution(object):
    def plusOne(self, digits):
    """
    从后往前找第一个不为9的元素,并将该位置后的9置零
    :type digits: List[int]
    :rtype: List[int]
    """
    n = len(digits)
    for i in range(n - 1, -1, -1):
    if digits[i] != 9:
    digits[i] += 1
    for j in range(i + 1, n):
    digits[j] = 0
    return digits
    return [1] + [0] * n

    def plusOne1(self, digits):
    """将数组转化为数字加一再将结果转化为整数数组"""
    num = ""
    for digit in digits:
    num += str(digit)
    return list([int(ch) for ch in str(int(num) + 1)])


    if __name__ == "__main__":
    slt = Solution()
    # result = slt.plusOne([1, 2, 3])
    result = slt.plusOne1([1, 2, 3])
    print(result)

35.搜索插入位置

题目描述

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。

示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1

题目链接

思路

  1. 利用二分查找目标值,如果存在,返回其索引,如果不存在,寻找插入位置。
    (1)二分查找找到目标值,时间复杂度为O(log n)
    (2)二分查找没找到目标值,时间复杂度为O(log n) + O(n)
    因此,该方法会时间复杂度不符合题意。
  2. 根据题意,找到大于等于目标值的位置,该位置即为插入位置/目标值的位置。
    该方法需要遍历数组,因此时间复杂度为O(n),不符合题意。
  3. 二分查找变形

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    class Solution(object):
    def searchInsert(self, nums, target):
    """
    利用二分查找目标值,如果存在,返回其索引,如果不存在,寻找插入位置。
    (1)二分查找找到目标值,时间复杂度为O(log n)
    (2)二分查找没找到目标值,时间复杂度为O(log n) + O(n)
    :type nums: List[int]
    :type target: int
    :rtype: int
    """
    index = self.binarySearch(nums, 0, len(nums), target)
    if index != -1:
    return index
    else:
    return self.findBigger(nums, target)

    def binarySearch(self, arr, low, high, key):
    if low <= high:
    mid = (low + high) // 2
    if arr[mid] == key:
    return mid
    elif arr[mid] > key:
    return self.binarySearch(arr, low, mid - 1, key)
    elif arr[mid] < key:
    return self.binarySearch(arr, mid + 1, high, key)
    return -1

    def findBigger(self, arr, num):
    if num < arr[0]:
    return 0
    if num > arr[len(arr) - 1]:
    return len(arr)
    for i in range(len(arr)):
    if arr[i] < num:
    continue
    else:
    break
    return i

    def searchInsert1(self, nums, target):
    """
    找到大于等于目标值的位置,该位置即为插入位置/目标值的位置。
    :type nums: List[int]
    :type target: int
    :rtype: int
    """
    if target < nums[0]:
    return 0
    if target > nums[len(nums) - 1]:
    return len(nums)

    for i in range(len(nums)):
    if nums[i] >= target:
    return i
    elif nums[i] < target:
    continue
    return i

    def searchInsert2(self, nums, target):
    """searchInsert1的简化版"""
    if target > nums[len(nums) - 1]:
    return len(nums)

    for i in range(len(nums)):
    if nums[i] < target:
    continue
    else:
    break
    return i

    def searchInsert3(self, nums, target):
    """
    二分查找变形
    不断用二分法逼近查找第一个大于等于 target的下标
    """
    l = 0
    r = len(nums) - 1
    while l <= r:
    mid = l + (r - l) // 2
    if nums[mid] < target:
    l = mid + 1
    else:
    r = mid - 1
    return l


    if __name__ == "__main__":
    slt = Solution()
    # result = slt.searchInsert([1, 3, 5, 6], 7)
    # result = slt.searchInsert1([1, 3, 5, 6], 7)
    # result = slt.searchInsert2([1, 3, 5, 6], 7)
    result = slt.searchInsert3([1, 3, 5, 6], 7)
    print(result)

7.21开发测试面经

  • sql语句

    表结构

    ​ 表名:student
    ​ 字段:id name score

    问题:成绩倒数第二/正数第二的学生名字

    SELECT student.name, student.scores FROM student ORDER BY scores DESC LIMIT 1, 1

    SELECT student.name, student.scores FROM student ORDER BY scores ASC LIMIT 1, 1

  • 内外连接

    SELECT student.name, student.scores, class.id FROM student INNER JOIN class ON student.classid = class.id

    SELECT student.name, student.scores, class.id FROM student LEFT JOIN class ON student.classid = class.id

    SELECT student.name, student.scores, class.id FROM student RIGHT JOIN class ON student.classid = class.id

  • selenium定位元素

    1
    2
    3
    4
    5
    6
    7
    8
    driver.find_element_by_xpath()
    driver.find_element_by_name()
    driver.find_element_by_tag_name()
    driver.find_element_by_link_text()
    driver.find_element_by_partial_link_text()
    driver.find_element_by_class_name()
    driver.find_element_by_css_selector()
    driver.find_element_by_id()
  • tcp三次握手?握手的时候怎么确认对方的身份?

  • TCP四次挥手

  • 网络七层模型及各层常见协议
    在这里插入图片描述

  • 算法

    • 两数之和

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      class Solution(object):

      def twoSum(self, nums, target):

      hashtable = dict()
      for i,num in enumerate(nums):
      if target - num in hashtable:
      return [hashtable[target-num], i]
      hashtable[nums[i]] = i
      return []
    • 实现LRU
      LRU

27.移除元素

题目描述

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

题目链接

思路

  1. 双指针
    设置两个指针,左指针left,右指针right,左指针left指向待插入不等于val的值,right指针遍历寻找不等于val的值,如果找到,就将right指针指向的值复制到left指针指向的位置,
    然后left指针后移到下一个待插入位置,right指针继续后移寻找下一个不等于val的值,依次类推。

  2. 双指针优化
    如果左指针 left 指向的元素等于 val,此时将右指针 right 指向的元素复制到左指针 left 的位置,然后右指针 right 左移一位。如果赋值过来的元素恰好也等于 val,可以继续把右指针 right 指向的元素的值赋值过来(左指针 left 指向的等于 val 的元素的位置继续被覆盖),直到左指针指向的元素的值不等于 val 为止。
    当左指针 left 和右指针 right 重合的时候,左右指针遍历完数组中所有的元素。
    这样的方法两个指针在最坏的情况下合起来只遍历了数组一次。与方法一不同的是,方法二避免了需要保留的元素的重复赋值操作。

阅读全文 »

26.删除有序数组中的重复项

题目描述

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

题目链接

思路

  1. 双指针
    (1)如果数组为空,返回0
    (2)如果数组只有一个元素,返回1
    (3)如果数组中有超过两个元素,第一个元素肯定不会被删除,所以从第二位位置开始删除重复元素,设置两个指针,一个快指针
    fast,一个慢指针slow,快指针fast用来遍历数组寻找下一个不重复元素,慢指针slow指向存放下一个不重复元素的位置;每当
    fast指针遍历到一个新的不重复元素(fast指向的元素不等于fast-1位置的元素),就将该元素复制到慢指针slow执行的位置,
    同时慢指针slow指向下一个位置,快指针fast继续寻找下一个不重复元素,依次类推。

阅读全文 »

121.买卖股票的最佳时机

题目描述

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

题目链接

思路

  1. 暴力法

  2. 一次遍历
    遍历一遍数组,计算每次 到当天为止 的最小股票价格和最大利润。

3. 动态规划
动态规划一般分为一维、二维、多维(使用状态压缩),对应形式为 dp(i)、dp(i)(j)、二进制dp(i)(j)。
(1)动态规划做题步骤
明确 dp(i) 应该表示什么(二维情况:dp(i)(j));
根据 dp(i)和 dp(i−1) 的关系得出状态转移方程;
确定初始条件,如 dp(0)。
(2)本题思路
其实方法一的思路不是凭空想象的,而是由动态规划的思想演变而来。这里介绍一维动态规划思想。
dp[i] 表示前 i 天的最大利润,因为我们始终要使利润最大化,则:

dp[i]=max(dp[i−1],prices[i]−minprice)
阅读全文 »

136.只出现一次的数字

题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:
输入: [2,2,1]
输出: 1

题目链接

思路

  1. python版本
    遍历nums数组中的每一个数num,并使用list.count(num)统计num在nums中出现的次数,如果次数为1,返回num。
  2. java版本
    遍历nums数组中的每一个数num,使用HashMap记录每个num出现的次数,然后返回出现次数为1的num。
阅读全文 »

283.移动零

题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

题目链接

思路

使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。
右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。

注意到以下性质:
(1)左指针左边均为非零数;
(2)右指针左边直到左指针处均为零。

因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。

阅读全文 »