代码随想录Day38

435.无重叠区间

题目:435. 无重叠区间 - 力扣(LeetCode)

思路:从小到大排序集合,之后一旦重叠就抛弃右边的一个,然后用左边的一个跟下一个接着判断是否重叠,无法处理【1,2】【1,100】这样的区间,加了if函数通过了,但是无法大通过全部测试用例

尝试(部分AC)
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        Arrays.sort(intervals,(a,b)->{
            if(a[0] == b[0]) return a[1] - b[1];
            return a[0]-b[0];
        });
        // Arrays.sort(intervals,(a,b) -> Integer.compare(a[0],b[0]));

        int count = 0;
        for(int i = 1;i < intervals.length; i++){
            if(intervals[i][0] == intervals[i-1][0]){
                intervals[i][1] = intervals[i-1][1];
                count++;
                continue;
            }
            if(intervals[i][0] < intervals[i-1][1]){
                count++;
                intervals[i][1] = intervals[i-1][1];
            }
        }
        return count;
    }
}
答案
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        Arrays.sort(intervals, (a,b)-> {
            return Integer.compare(a[0],b[0]);
        });
        int count = 1;
        for(int i = 1;i < intervals.length;i++){
            if(intervals[i][0] < intervals[i-1][1]){
                intervals[i][1] = Math.min(intervals[i - 1][1], intervals[i][1]);
                continue;
            }else{
                count++;
            }    
        }
        return intervals.length - count;
    }
}
小结
  • 取 区间1 和 区间2 右边界的最小值,因为这个最小值之前的部分一定是 区间1 和区间2 的重合部分,如果这个最小值也触达到区间3,那么说明 区间 1,2,3都是重合的。
  • 卡尔的思路是反过来的,先计算没有交叉的区间个数,再用总数去减,就得到了结果

763.划分字母区间

题目:763. 划分字母区间 - 力扣(LeetCode)

思路:把字符串转换为数字吗?ASCII码转出来还是不知道怎么处理,我想的是扫描字符串,把相同字母的离得最远的两个当作左右边界,排序之后,遍历融合区间,之后遍历集合,把数字加起来,我怎么知道哪个是末尾的a呢,啊哈,不断取最大的下标

尝试(有思路,代码写不出来)
class Solution {
    public List<Integer> partitionLabels(String s) {
        int[][] temp = createIntervals(s);
        // 讲temp数组排序
        Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
        // 遍历temp数组,把相交的区间融合在一起,放入到新的数组
        List<int[][]> merged = new ArrayList<>();
        
        for (int i =1; i < temp.length; i++) {
            if (temp[i][0] < temp[i-1][1]) {
               merged.add(new int[temp[i-1][0],temp[i][1]]);
            }else{
                merged.add(new int[temp[i][0],temp[i][1]]);
            }
        }
        
        // 将结果转换为数组
        int[][] mergedIntervals = merged.toArray(new int[merged.size()][]);
        // 遍历新的数组,挨个取出区间长度+1,组成结果数组
        int result = 0;
        for(int[][] p : mergedIntervals){
            result +=p[1]-p[0]+1;
        }
        return result;
    }
    public static int[][] createIntervals(String str) {
        HashMap<Character, List<Integer>> map = new HashMap<>();
        int[][] temp = new int[str.length()][2];

        // 遍历字符串,记录每个字符的下标
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            map.putIfAbsent(c, new ArrayList<>());
            map.get(c).add(i);
        }

        // 根据下标列表创建区间
        int index = 0; // temp数组的索引
        for (List<Integer> indices : map.values()) {
            if (indices.size() > 1) {
                // 只有当有多个相同字符时才创建区间
                temp[index][0] = indices.get(0); // 区间的左边界
                temp[index][1] = indices.get(indices.size() - 1); // 区间的右边界
                index++;
            }
        }

        // 如果需要,可以截断temp数组以去除未使用的部分
        int[][] result = new int[index][2];
        System.arraycopy(temp, 0, result, 0, index);
        return result;
    }
}
答案
class Solution {
    public List<Integer> partitionLabels(String S) {
        List<Integer> list = new LinkedList<>();
        int[] edge = new int[26];
        char[] chars = S.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            edge[chars[i] - 'a'] = i;
        }
        int idx = 0;
        int last = -1;
        for (int i = 0; i < chars.length; i++) {
            idx = Math.max(idx,edge[chars[i] - 'a']);
            if (i == idx) {
                list.add(i - last);
                last = i;
            }
        }
        return list;
    }
}
小结
  • 哥们,你的思路好像可行,但是不够简洁,卡尔的思路是,先遍历字符串,记录所有字符的最远位置,存入edge数组,之后遍历edge数组,目标是找到分割线,挨个取出元素与当前idx比较,如果元素比当前idx大,就更新idx,直到遍历到idx对应的下标处,把(i-last)存入结果list,更新last
  • 每次遇到新字母【new】,就要走到这个字母的最远处,这样才能保证所有【new】只出现在一个区间
  • 记录字母最远的边界,用【int[] edge = new int[26];】和【edge[chars[i] - 'a']】

56.合并区间

题目:56. 合并区间 - 力扣(LeetCode)

思路:以为很简单,遇到重叠的,叠一下加入结果数组,不重叠的,就把前一个加入结果数组

尝试(标题4)
class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals,(a,b)->{
            return a[0]-b[0];
        });
        List<int[]> result = new LinkedList<>();
        if(intervals.length == 1) return intervals;
        for(int i =1; i< intervals.length; i++){
            if(intervals[i][0]<=intervals[i-1][1]){
                intervals[i][0] = Math.min(intervals[i][0],intervals[i-1][0]);
                intervals[i][1] = Math.max(intervals[i][1],intervals[i-1][1]);
                result.add(new int[]{intervals[i][0], intervals[i][1]}); 
            }else{
                if(i==1){
                    result.add(new int[]{intervals[i-1][0], intervals[i-1][1]});
                }else{
                    result.add(new int[]{intervals[i][0], intervals[i][1]}); 
                }
            }  
        }
        return result.toArray(new int[result.size()][]);
    }
}
答案
class Solution {
    public int[][] merge(int[][] intervals) {
        List<int[]> res = new LinkedList<>();
        //按照左边界排序
        Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0]));
        //initial start 是最小左边界
        int start = intervals[0][0];
        int rightmostRightBound = intervals[0][1];
        for (int i = 1; i < intervals.length; i++) {
            //如果左边界大于最大右边界
            if (intervals[i][0] > rightmostRightBound) {
                //加入区间 并且更新start
                res.add(new int[]{start, rightmostRightBound});
                start = intervals[i][0];
                rightmostRightBound = intervals[i][1];
            } else {
                //更新最大右边界
                rightmostRightBound = Math.max(rightmostRightBound, intervals[i][1]);
            }
        }
        res.add(new int[]{start, rightmostRightBound});
        return res.toArray(new int[res.size()][]);
    }
}
小结
  • 定义左右边界,遍历数组,左右边界跟下一个区间有相交,就更新右边界,否则把左右边界构成的区间加入结果数组,把下一个区间当作左右边界,最后要加上左右边界
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值