数据结构与算法

1.给定一个整形数组,是否能找出其中的两个数使得其和为某个指定的值?

  • 示例: 输入数组为{1, 5, 7, 3}, 指定值为10, 则我们可以从中找出两个数3和7, 和等于10。

暴力穷举: 时间复杂度 O(n^2)

def hasSum(array, target_number):
   len_array = len(array)

   for i in range(0, len_array - 1):
       for j in range(len_array - 1, i, -1):
           while array[i] + array[j] == target_number:
               return (1, array[i], array[j])

   return (0, None, None)


if __name__ == '__main__':
   array = [1, 5, 7, 3, 2]
   target_number = 5
   result, a, b = hasSum(array, target_number)

   if result == 1:
       print('YES, %d + %d = %d' % (a, b, target_number))
   else:
       print('NO')
       

优化算法:



2.股票买卖,给定一个数组,第i个元素代表第i天的股价。假设最多允许进行1次买卖,求可能的最大利润是多少?

  • 示例: 输入price = [12, 15, 14, 8, 11, 10, 12], 则输出最大利润是4。
    暴力穷举:
def maxProfit(price):
    all_num = []
    len_price = len(price)
    for i in range(len_price):
        for j in range(i + 1, len_price):
            num = price[j] - price[i]
            all_num.append(num)
    return max(all_num)


if __name__ == '__main__':
    price = [12, 15, 14, 8, 11, 10, 12]
    result = maxProfit(price)
    print(result)
    

算法优化:

'''
解题思路
到最后交易结束时,一共会有3种状态:

dp0:一直不买
dp1:只买了一次
dp2:买了一次,卖了一次
初始化3种状态:

dp0 = 0
dp1 = - prices[0]
dp2 = float("-inf")
因为第一天不可能会有dp2状态,因此将dp2置为负无穷
(Java中置为int的下边界)
对3种状态进行状态转移:

dp0 = 0
一直为0
dp1 = max(dp1, dp0 - prices[i])
前一天也是dp1状态,或者前一天是dp0状态,今天买入一笔变成dp1状态
dp2 = max(dp2, dp1 + prices[i])
前一天也是dp2状态,或者前一天是dp1状态,今天卖出一笔变成dp2状态
最后一定是手里没有股票赚的钱最多,因此返回的是dp0,dp2的最大值
'''

def maxProfit(prices) -> int:
    dp0 = 0             # 一直不买
    dp1 = - prices[0]   # 只买了一次
    dp2 = float('-inf') # 买了一次,卖了一次

    for i in range(1, len(prices)):
        dp1 = max(dp1, dp0 - prices[i])
        dp2 = max(dp2, dp1 + prices[i])
    return max(dp0, dp2)


'''
复杂度分析
时间复杂度:O(n)O(n)
空间复杂度:O(1)O(1)
'''

3.给定两个数组表示的整数, 比如 x=1234=[1, 2, 3, 4], y=2410=[2, 4, 1, 0], 返回第一个整数重组后的值最接近第二个整数, 并且大于第二个整数。假设两个整数的数组大小相同,并且肯定能找出符合条件的数。

  • 示例: 输入[1, 2, 3, 4]和[2, 4, 1, 0], 返回[2, 4, 1, 3] or ‘2413’
# 函数调用格式如下
def getclosenumber(x, y):
    # x 重组后, 大于 y
    y = int(''.join([str(a) for a in y]))
    x = [str(b) for b in sorted(x)]
    n = len(x)
    used = []  # 用来存放已经用过的数字
    path = []  # 用来存放符合条件的结果

    # 现排序x, 然后使用回溯算法暴力求解
    def backtrack():
        if len(path) == n and int(''.join(used)) > y:
            # print(int(''.join(used)))
            return int(''.join(used))
        for i in range(0, n):
            if x[i] in used:
                continue
            path.append(x[i])
            used.append(x[i])
            ret = backtrack()
            if ret:
                return ret
            else:
                used.pop()
                path.pop()

    return backtrack()


def main():
    x = [1, 2, 3, 4]
    y = [2, 4, 1, 0]
    res = getclosenumber(x, y)
    print("res=%s" % res)


if __name__ == '__main__':
    main()
    

4.快速排序

def quick_sort(list1, start, end):
    """快速排序"""

    # 递归的结束条件
    if start >= end:
        return

    # 界限值
    mid = list1[start]
    # 左右游标
    left = start
    right = end

    while left < right:
        # 从右边开始找寻小于mid的值 归类到左边
        while list1[right] >= mid and left < right:
            right -= 1
        list1[left] = list1[right]
        # 从左边开始找寻大于mid的值 归类到右边
        while list1[left] < mid and left < right:
            left += 1
        list1[right] = list1[left]

    # 循环一旦结束了 证明找到了mid应该在的位置
    list1[left] = mid

    # 递归操作
    quick_sort(list1, start, left - 1)
    quick_sort(list1, right + 1, end)


if __name__ == '__main__':
    array1 = [3, 6, 9, 2, 4, 8, 15, 17]
    quick_sort(array1, 0, len(array1) - 1)
    print(array1)
    

5.蛙跳,给出一维非负元素的数组,每个元素代表该元素位置能够跳的最远距离。假设初始位置在第一个元素,请根据输入数组判断是否能跳到数组的末尾。

  • 示例:

    • 输入数组 A = [2, 1, 3, 1, 1], 输出True
    • 输入数组 A = [3, 2, 1, 0, 1], 输出False
def canJump(nums):
    max_i = 0  # 初始化当前能到达最远的位置
    for i, jump in enumerate(nums):  # i为当前位置,jump是当前位置的跳数
        if max_i >= i and i + jump > max_i:  # 如果当前位置能到达,并且当前位置+跳数>最远位置
            max_i = i + jump  # 更新最远能到达位置
    return max_i >= i


if __name__ == '__main__':
    a = [2, 1, 3, 1, 1]
    b = [3, 2, 1, 0, 1]
    res = canJump(a)
    print(res)
    

6. 给出一个单向链表的头指针, 如果链表有环, 则返回环的长度, 否则返回0.

  • 示例: head -> 3 -> 8 -> 7 -> 1 -> 2 -> 3 -> 4 -> 5 -> 1, 则返回5
class ListNode(object):
    def __init__(self, value=0):
        self.value = value
        self.next_node = None


def lengOfCircle(node):
    # 如果头节点为为空则返回0
    if not node:
        return 0
    # 计数器
    count = 1
    # 定义头为node
    head = node
    # 下一个就是node的下一个
    next = node.next_node
    # 当next存在
    while next:
        # 如果next不是头
        if next != head:
            # 计数器+1
            count += 1
            # 下一个就是node的下一个
            next = next.next_node
        else:
            # 返回长度
            return count
    return 0


# 下面完成构造链表的代码
# 3 -> 8 -> 7 -> 1 -> 2 -> 3 -> 4 -> 5 -> 1
def main():
    head = ListNode(3)
    one = ListNode(8)
    two = ListNode(7)
    three = ListNode(1)
    four = ListNode(2)

    head.next_node = one
    one.next_node = two
    two.next_node = three
    three.next_node = four
    four.next_node = head
    # 调用你编写的代码函数, 唯一的参数是头指针head
    res = lengOfCircle(head)
    print(res)


if __name__ == '__main__':
    main()
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值