1.题号68.绿洲之旅:最少补给次数探索
题目描述不在重复,本题考虑使用贪心算法,找到当前能够到达的所用位置,再比较这些位置中哪些位置能够加的水最多,走到这个点,更新参数再走下一个点,直到剩余的水能走完所有路程
完整代码如下:
def find_can_arrive(current_water, position, supply, current_position): # 找到能够到达的位置,且位置能加的水最多 now_water = 0 next_position = None for i in range(current_position + 1, len(position)): if position[i] <= current_water: if supply[i] > now_water: next_position = i now_water = supply[i] else: break return next_positiondef solution(d, w, position, supply): current_position = -1 current_water = w result = 0 go = 0 # 只要没办法让距离归0,就继续走 while d - current_water > 0: next_position = find_can_arrive(current_water, position, supply, current_position) if next_position ==None: return -1 go = position[next_position] d -= go current_water = current_water - go + supply[next_position] current_position = next_position result += 1 position = [elem - go for elem in position] return result
现在逐行对代码进行解释,针对函数find_can_arrive,首先设立两个临时变量now_water = 0
next_position = None,一个用来记录当前位置的补给水量,一个用来返回下一个要到达的点
使用一个for循环遍历从当前位置之后的每一个位置,如果当前的水量足够到达下一个位置,并且下一个位置的水量比之前记录的最大水量还要多,我们就一直更新now_water和next_position知道我们找到的下一个位置是能都到达的地方可补给水最多的
针对solution函数,我使用一个while循环,只要剩余距离大于0,就继续寻找下一个能到达的位置。 调用find_can_arrive函数来确定下一个能到达的位置。 如果没有位置能到达(next_position为None),就返回-1。 同时更新剩余距离(d)、当前水量(current_water)、当前位置(current_position)和结果(result)即步数。最后当这个循环跳出,我们就可以得到结果
2.题号31不同整数计数问题
本题主要考察一个正则表达式的应用,判断非数字并将它替换成空格,以空格为标准划分字符串为列表,然后遍历这个列表去掉前导0,最后返回长度得到结果
完整代码如下
def solution(word: str) -> int: # 使用正则表达式将非数字字符替换为空格 import re replaced_word = re.sub(r'[^0-9]', ' ', word) unique_numbers =[] # 使用split方法将替换后的字符串拆分为整数列表 numbers = replaced_word.split() # 去除前导零并存储为集合以获取唯一值 for i in numbers: j = int(i) if j not in unique_numbers: unique_numbers.append(j) # 返回不同整数的数量 return len(unique_numbers)
3.题号99.糖果传递游戏
针对该题的糖果分配规则
- 每个糖果都会先从第一个小朋友开始分配。如果当前小朋友的糖果数量(包括新分配的糖果)小于或等于他的右边的小朋友,则他会保留这个糖果。
- 如果当前小朋友的糖果数量大于他右边的小朋友,他会将这个糖果传递给下一个小朋友。
- 这个过程会持续,直到糖果传递到第
n个小朋友。如果第n个小朋友也不能保留这个糖果,那么糖果会被传递给小U。
就是该题的编码思路,写一个for循环,遍历糖果数,有几个糖果遍历几次,按照上面的规则遍历糖果,并判断该糖果会被传递到哪里,同时记录位置与当前的分配状态,当遍历到最后一个,返回位置
def solution(n, m, a): for candy in range(m): # 存储当前糖果分配状态与位置,每次位置清0 current = a.copy() pos = 0 while pos < n: # 添加糖果 current[pos] += 1 # 检查是否需要传递给下一个小朋友 if pos < n - 1: # 不是最后一个小朋友 if current[pos] > current[pos + 1]: pos += 1 # 传递给下一个小朋友 else: # 当前小朋友可以保留糖果 if candy == m - 1: # 如果是最后一颗糖果 return pos + 1 # 返回索引 # 更新实际的糖果数组 a[pos] = current[pos] break else: # 是最后一个小朋友 # 最后一个小朋友的糖果一定传给小U,因为小U的糖果数可以认为是无限大 if candy == m - 1: # 如果是最后一颗糖果 return n + 1 # 给小U break # 如果糖果传递完整个队列或传给了最后一个小朋友 if pos == n - 1: if candy == m - 1: # 如果是最后一颗糖果 return n + 1 # 返回小U的位置 elif pos < n - 1:#不是就更新状态 a[pos] = current[pos]
4.题号36,饭馆菜品选择问题
本体我的主要解决思路是使用while循环判断选了几道菜,每选到一道菜K就减一,同时记录选到的菜有没有蘑菇,还能不能选到有蘑菇的菜,能够正常吧k减到0就返回价格,反之就返回-1,时间复杂度为logn,详细代码如下
def solution(s: str, a: list[int], m: int, k: int) -> int: b = a[:] # 复制列表 a s1 = list(s) # 将字符串 s 转换为字符列表,以便进行修改 result = 0 if k > len(b): return -1 while(k>0): # 找到列表 b 中的最小值及其索引 min_val = min(b) index = b.index(min_val) # 根据字符和 m 的值进行条件判断 if s1[index] == '0': result += min_val b.pop(index) # 从列表 b 中移除最小值 s1.pop(index) # 从字符列表 s1 中移除对应位置的字符 k-=1 continue elif s1[index] == '1' and m > 0: result += min_val m -= 1 b.pop(index) # 从列表 b 中移除最小值 s1.pop(index) # 从字符列表 s1 中移除对应位置的字符 k-=1 continue elif s1[index] == '1' and m <= 0 and len(b) ==1: return -1 elif s1[index] == '1' and m <= 0 and len(b) !=1: b.pop(index) # 从列表 b 中移除最小值 s1.pop(index) # 从字符列表 s1 中移除对应位置的字符 continue return result