Top 100 Linked Question 修炼------第34题、第39题

34. Find First and Last Position of Element in Sorted Array

题目链接

题目解释:首先我们看题目的大体解释,给出一个已经排好序的list,这个list中是存在重复元素的,我给定一个target,需要在这个list,要求在在O(lgN)的时间内找到这个target的起始位置和终止位置,若找不到这样的元素,则返回[-1,-1]

题目示例:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

说明:target=8 是在第三个位置开始,在第四个位置结束,所以返回的结果是[3,4]

Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

说明:target=6,这个元素找不到,所以返回的结果是[-1,-1]

题目分析:题目给出了暗示,假设你对数据结构存在一定的意识的话,那么一定可以想到题目要求的是O(lgN)的时间复杂度,而且给出的list是已经排好序的,那么一定是基于二分法,同样的,本题也不例外,也是采用基于二分法的思想,先找到等于target的最左边的元素,然后往右遍历,直至右边的一个数不等于target为止,这样得到的中间的序列就是起始位置与终止位置。

本题的一个不同点是,不仅仅是需要找到等于target的那个值,还要找到最左边的那个target的值,这样才是关键。在这里主要是采用了一个变量的trick,从而来判断是左还是右。

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        # 首先是找到这个节点的位置
        left_idx = self.extreme_insertion_index(nums, target, True)
        # 判断需要找的元素是否在target中
        if left_idx == len(nums) or nums[left_idx] != target:
            return [-1, -1]
        return [left_idx, self.extreme_insertion_index(nums, target, False)-1]
    def extreme_insertion_index(self, nums, target, left):
        lo = 0
        hi = len(nums)
        while lo < hi:
            mid = (lo + hi) // 2
            if nums[mid] > target or (left and target == nums[mid]):
                hi = mid
            else:
                lo = mid+1
        return lo

39. Combination Sum

题目链接

题目分析:给出一个set(就是不包含重复元素的list)和一个target,要求你找到这个list中任取几个数(可以重复)相加,使其和等于target。要求最后的结果中不能包含重复的list.

示例:
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
  [7],
  [2,2,3]
]

结合题目解释一下:给出的一个list为上面的candidates,目标所期望取得的加和target=7,所有最后的结果中存在[[7],[2,2,3]]这连个元素

题目解答:首先看到这个题目的时候我觉得很是似曾相识,然后一回想,确实,一下子就让我想到了leetcode中的另外一个题,PathSum,直接说一下解题方法吧,很明显,我们这个题目是可以采用回溯法来解决的。具体的回溯解答方式我们可以尝试去看代码解决。

回溯法一般就是经过三个步骤:

① 外层循环逐一往中间集合 temp 中加入元素 nums[i],使这个元素处于存在状态

② 开始递归,递归中携带加入新元素的 temp,并且下一次循环的起始是 i 元素的下一个,因而递归中更新 i 值为 i + 1

③ 将这个从中间集合 temp 中移除,使该元素处于不存在状态

在本题中,可以先将给定的list进行排序(为了剪枝),然后再进行深度优先遍历。

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        self.resList = []
        # 排序,方便后面的剪枝
        candidates = sorted(candidates)
        self.dfs(candidates,[],target,0)
        return self.resList
    def dfs(self, candidates, sublist, target, last):
        # 加入到后序的序列
        if target == 0:
            self.resList.append(sublist[:])
            return
        # 已经小于第一个元素了,那么可以产生剪枝操作,直接返回
        if target< candidates[0]:
            return 
        for n in candidates:
            if n > target:
                return
            if n < last:
                continue
            sublist.append(n)
            self.dfs(candidates,sublist,target - n, n)
            sublist.pop()

总结

多刷一些题目,思路还是会更加开阔的......

猜你喜欢

转载自blog.csdn.net/sir_TI/article/details/88786553