代码随想录算法训练营第三十五天|LeetCode435,763,56

435.无重叠区间

题目要求移除区间的数量最小,是剩余区间不重复

思路:

将intervals按照第一个值的升序排序。然后跟昨天气球的思路一样

第一次错误:

重写的Comparator乜有满足自反性,传递性,对称性

自反性:当 两个相同的元素相比时,compare必须返回0,也就是compare(o1, o1) = 0;

反对称性:如果compare(o1,o2) = 1,则compare(o2, o1)必须返回符号相反的值也就是 -1;

传递性:如果 a>b, b>c, 则 a必然大于c。也就是compare(a,b)>0, compare(b,c)>0, 则compare(a,c)>0

解决方式:

Arrays.sort(intervals,(a,b)->{
    if (a[0] < b[0]){
        return -1;
    }
    return 1;
});

修改为
  Arrays.sort(intervals,(a,b)->{
            return Integer.compare(a[0],b[0]);
        });
public class LeetCode435 {
    public int eraseOverlapIntervals(int[][] intervals) {

        //记录删除的区间数目
        int count = 0;
        //对intervals按照升序排序
        Arrays.sort(intervals,(a,b)->{
            return Integer.compare(a[0],b[0]);
        });

        for(int i = 1;i < intervals.length;i++){
            //如果出现了重叠的区间,则将后面的那个删掉
            if (intervals[i][0] >= intervals[i-1][0] && intervals[i][0] < intervals[i-1][1] ){
                intervals[i][1] = Math.min(intervals[i-1][1],intervals[i][1]);
                count++;
            }
        }

    return count;
    }

763.划分字母区间

读了好几遍题,才了解到“同一字母最多出现在一个片段中”并不是指具体的哪一个字母“

题目要求划分后仍然顺序链接后仍然是原来的字符串,所以不能排序之类的

没思路,看题解:

在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。

可以分为如下两步:

  • 统计每一个字符最后出现的位置
  • 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点

主要是这个第二步,你遍历字符串的时候,就相当于一直在更新当前区间内所有字母可以出现的最远位置,那一旦当前的索引与最远位置相等了,那么就表明,当前这个区间已经找完了。由于题目要求是尽可能多的分隔字符串,那我们要保证同一区段内尽可能少的有不同字母。

第一次错误:

使用last记录上一次分割位置的时候,last要初始化为 -1.


public List<Integer> partitionLabels(String s) {
        List<Integer> result = new ArrayList<>();
        int[] end = new int[26];
        //遍历字符串,记录每个字符在字符串中结束的位置。
        for ( int i =  0 ; i < s.length();i++){
            end[s.charAt(i) - 'a'] = i;
        }
        //记录当前区间内字母最远出现的距离
        int max = -1;
        //记录上一区间的最远距离(即上一分割点的位置)
        int last = 0;

        for (int i = 0; i<s.length(); i++){
            max = Math.max(end[s.charAt(i) - 'a'],max);
            if (i == max){
                result.add(max-last);
                last = i;
            }

        }

        return result;


    }

56. 合并区间

这个与今天的重叠区间题类似。不过本题并不是要取最小值,而是要不断的扩展范围。

第一次错误:

最后一个值没有加进来,所以在for循环结束后,把最后一个值也加到结果里面。

 public int[][] merge(int[][] intervals) {

        List<int[]> tmp = new ArrayList<>();
        //将intervals安装start升序进行排序
        Arrays.sort(intervals, (a,b)->{
            return Integer.compare(a[0],b[0]);
        });
        for (int i = 1; i < intervals.length;i++){
            //如果第二个区间与第一个区间有重叠的地方
            if (intervals[i][0] <= intervals[i-1][1]&& intervals[i][0] >= intervals[i-1][0]){
                intervals[i][0] = intervals[i-1][0];
                intervals[i][1] = Math.max(intervals[i][1],intervals[i-1][1]);
            }else {
                tmp.add(intervals[i-1]);
            }

        }
        //要把最后一个结果也加上。
        tmp.add(intervals[intervals.length -1]);

        return tmp.toArray(new int[tmp.size()][]);

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值