算法刷题:2020.六月

中等

(LC)853. 车队

题目

N 辆车沿着一条车道驶向位于 target 英里之外的共同目的地。
每辆车 i 以恒定的速度 speed[i] (英里/小时),从初始位置 position[i] (英里) 沿车道驶向目的地。
一辆车永远不会超过前面的另一辆车,但它可以追上去,并与前车以相同的速度紧接着行驶。
此时,我们会忽略这两辆车之间的距离,也就是说,它们被假定处于相同的位置。
车队 是一些由行驶在相同位置、具有相同速度的车组成的非空集合。注意,一辆车也可以是一个车队。
即便一辆车在目的地才赶上了一个车队,它们仍然会被视作是同一个车队。
会有多少车队到达目的地?

示例:
输入:target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3]
输出:3
解释:
从 10 和 8 开始的车会组成一个车队,它们在 12 处相遇。
从 0 处开始的车无法追上其它车,所以它自己就是一个车队。
从 5 和 3 开始的车会组成一个车队,它们在 6 处相遇。
请注意,在到达目的地之前没有其它车会遇到这些车队,所以答案是 3。

解法:【先对position进行排序】

#解法思路
#首先要对车辆初始位置进行排序@@@@@@
#首先计算出每辆车理论上的抵达时间 arr_time(无前车阻碍的情况下)
#依次判断arr_time是否比前车arr_time短
#如果理论上前车更早抵达,则会因为受到阻挡而与前车同属一个车队,否则就是下一个车队的头车
class Solution:
    def carFleet(target, position, speed):
        if not position:
            return 0
			
		ps = sorted(zip(position,speed),reverse=True)
		arr_time = []
		for p,s in ps:
			time = (target - p)/s
			arr_time.append(time)
		
		group_nums = 0
		arrtime = -1
		for i in range(len(arr_time)):
			if arr_time[i] > arrtime:
				group_nums += 1
				arrtime = arr_time[i]
		return group_nums

错误解法:【未先对position进行排序】

#解法思路
#首先计算出每辆车理论上的抵达时间 arr_time(无前车阻碍的情况下)
#依次判断arr_time是否比前车arr_time短
#如果理论上前车更早抵达,则会因为受到阻挡而与前车同属一个车队,否则就是下一个车队的头车
class Solution:
    def carFleet(target, position, speed):
        if not list:
            return 0
			
        car_nums = len(position) 	#车辆数量
        group_nums = 0    			#记录车队数量
        arr_time = []     			#记录理论抵达时长列表
        while position:
            time = (target - position.pop())/speed.pop()
            arr_time.append(time)
        arr_time.reverse()
		
        arr_time_index = -1 #当前车队抵达时间(用于遍历)
        for i in range(car_nums):
            if arr_time[i] > arr_time_index:
                group_nums += 1
                arr_time_index = arr_time[i]                
        return group_nums

#测试代码 
target         =10
position     =[0,4,2]
speed         =[2,1,3]    
print(Solution.carFleet(target,position,speed))
#时间复杂度:O(N)
#空间复杂度:O(N)

(LC)1302. 层数最深叶子节点的和

题目

给你一棵二叉树,请你返回层数最深的叶子节点的和。
在这里插入图片描述
输入:root = [1,2,3,4,5,null,6,7,null,null,null,null,8]
输出:15

代码及思路1:深度优先搜索

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

#deepest_floor:记录最深的层数
#deepest_sum:记录最深层数的加和

#解法函数1:深度优先搜索
class Solution:
    def __init__(self):
        self.deepest_floor = -1
        self.deepest_sum = 0

    def deepestLeavesSum(self, root):
        def dfs(node, dep):
            if not node:
                return
            if dep > self.deepest_floor:
                self.deepest_floor, self.deepest_sum = dep, node.val
            elif dep == self.deepest_floor:
                self.deepest_sum += node.val
            dfs(node.left, dep + 1)
            dfs(node.right, dep + 1)
        
        dfs(root, 0)
        return self.deepest_sum
#时间复杂度:O(N):N为节点数量
#空间复杂度:O(H):H为树高度

#解法函数2:广度优先搜索
class Solution:
    def deepestLeavesSum(self, root):
        q = collections.deque([(root, 0)])
        deepest_floor, deepest_sum = -1, 0
        while len(q) > 0:
            node, dep = q.pop()
            if dep > deepest_floor:
                deepest_floor, deepest_sum = dep, node.val
            elif dep == deepest_floor:
                deepest_sum += node.val
            if node.left:
                q.append((node.left, dep + 1))
            if node.right:
                q.append((node.right, dep + 1))
        return deepest_sum

#时间复杂度:O(N):N为节点数量
#空间复杂度:O(H):H为树高度

(LC)16. 最接近的三数之和

题目

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

代码及思路

#解法说明
#对数组进行升序排序后
#设定res为无穷大,用于存储结果
#首先用遍历的方式挨个先锁定一个数nums[i]
#然后再将nums[i]之后的首尾两个数分别标记为nums[L],nums[R]
#获得cur_sum = nums[i] + nums[L] + nums[R]
#当cur_sum > target,则右移nums[L],使得cur_sum变大,接近target
#当cur_sum < target,则左移nums[R],使得cur_sum变小,接近target
#遍历完成后,res将会存下最接近target的和值

#解法函数
class Solution:
    def threeSumClosest(nums, target):
        nums.sort()
        n = len(nums)
        res = float("inf")
        
        if(n<3):
            return None
        
        for i in range(n):
            L = i+1
            R = n-1
            while L < R:
                cur_sum = nums[i] + nums[L] + nums[R]
                if(cur_sum == target):
                    return target
                if(abs(cur_sum - target) < abs(res - target)):
                    res = cur_sum
                if(cur_sum > target):
                    R -= 1
                if(cur_sum < target):
                    L += 1
        return res


#测试代码
nums = [-1,2,1,-4]
target = 1
print(Solution.threeSumClosest(nums,target))

#时间复杂度分析:排序{NlogN};双层循环{O(n)*O(n)}
#空间复杂度:O(1)

(LC)40. 组合总和 II

题目

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
来源:力扣(LeetCode)

代码及思路

#解法说明
#用给定数组 candidates{n} 组成 target ,假设结果集为result = [{a1},{a2},.....,{ak}],其中{ak}为
#cadidates{n}中的每一个数,在结果集的数组{ak}当中的,都有‘有’、‘无’两种状态,共有2^n种组合
#因此我们从第一个数开始,分‘有’、‘无’两种状态往下遍历,遍历所有可能的组合,并在终止条件发生时结束


#解法函数
class Solution:
    def combinationSum2(candidates, target):
        if target == 0 or len(candidates) == 0:
            return []
        result = []
		
        def helper(tar, idx, cur):
            if tar == 0:  		# 成功终止条件:剩余tar=0
                result.append(cur[:])
                return
            for i in range(idx, len(candidates)):
                if candidates[i] > tar:
                    break 		# 失败终止条件:下一个数大于剩余tar,无法继续加和
                if i > idx and candidates[i] == candidates[i - 1]:
                    continue 	# 跳过条件:重复数字跳过
                cur.append(candidates[i]) # 未触发终止或跳过条件则添加数字                
                helper(tar - candidates[i], i + 1, cur)#(分支1)包含cadidates[i]的结果往下层走
                cur.pop()  							   #(分支2)不包含cadidates[i]的结果在本层弹出candidates[i]继续循环

        candidates.sort()
        helper(target, 0, [])
        return result

#测试代码
candidates = [10,1,2,7,6,1,5]
target = 8
result = Solution.combinationSum2(candidates,target)
print(result)

猜你喜欢

转载自blog.csdn.net/qq_41960416/article/details/106638557