我是靠谱客的博主 过时豌豆,最近开发中收集的这篇文章主要介绍力扣每日练习-java版(五)31. 下一个排列49. 字母异位词分组1288. 删除被覆盖区间56. 合并区间986. 区间列表的交集,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

力扣每日练习-java版(五)

  • 31. 下一个排列
    • 思路
    • 代码
    • 时空复杂度
    • 备注
  • 49. 字母异位词分组
    • 思路
    • 代码
    • 时空复杂度
    • 备注
  • 1288. 删除被覆盖区间
    • 思路
    • 代码
    • 时空复杂度
    • 备注
  • 56. 合并区间
    • 思路
    • 代码
    • 时空复杂度
    • 备注
  • 986. 区间列表的交集
    • 思路
    • 代码
    • 时空复杂度
    • 备注

31. 下一个排列

https://leetcode-cn.com/problems/next-permutation/
在这里插入图片描述

思路

1.希望下一个数比当前数大
2.希望增加的幅度尽可能的小
根据以上两点要求,可以得出,我们要把低位的大数(尽可能小)和高位的小数交换,且尽量在低位做交换。
所以我们需要四步操作:
1.从右向左查找第一个相邻升序的元素对 (i,j),满足 A[i] < A[j]。此时 [j,end) 必然是降序
2.在 [j,end) 从右向左查找第一个满足 A[k] > A[i] 的 k。A[i]、A[k] 分别就是上文所说的「小数」、「大数」
3.将 A[i] 与 A[k] 交换
4.因为这时 [j,end) 必然是降序,要想让增加的幅度尽可能小,我们要逆置 [j,end)部分,使其升序
5.如果在步骤 1 找不到符合的相邻元素对,说明数组A从 [begin,end)整个范围都是降序顺序,则直接跳到步骤 4整体转换为升序

代码

class Solution {
    public void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        if (i >= 0) {
            int j = nums.length - 1;
            while (j >= 0 && nums[i] >= nums[j]) {
                j--;
            }
            swap(nums, i, j);
        }
        reverse(nums, i + 1);
    }

    public void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    public void reverse(int[] nums, int start) {
        int left = start, right = nums.length - 1;
        while (left < right) {
            swap(nums, left, right);
            left++;
            right--;
        }
    }
}

时空复杂度

1.时间复杂度
O(N),其中 N 为给定序列的长度。我们至多只需要扫描两次序列,以及进行一次反转操作。
2.空间复杂度
O(1),只需要常数的空间存放若干变量。

备注

1.算法中的交换、反转操作有多次时,可以考虑封装成函数

49. 字母异位词分组

https://leetcode-cn.com/problems/group-anagrams/
在这里插入图片描述

思路

1.排序
将字符串排序,所有源单词中的字母通常恰好只用一次,所以排序后都是一样的结果,排序后的结果作为key,源单词作为value,最后返回所有的value list即可。
2.计算字母出现次数
由于互为字母异位词的两个字符串包含的字母相同,因此两个字符串中的相同字母出现的次数一定是相同的,故可以将每个字母出现的次数使用字符串表示,作为哈希表的键。由于字符串只包含小写字母,因此对可以使用长度为 26 的数组记录每个字母出现的次数。

代码

方法一:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        for (String str : strs) {
            char[] array = str.toCharArray();
            Arrays.sort(array);
            String key = new String(array);
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            list.add(str);
            map.put(key, list);
        }
        return new ArrayList<List<String>>(map.values());
    }
}

方法二:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        for (String str : strs) {
            int[] counts = new int[26];
            int length = str.length();
            for (int i = 0; i < length; i++) {
                counts[str.charAt(i) - 'a']++;
            }
            // 将每个出现次数大于 0 的字母和出现次数按顺序拼接成字符串,作为哈希表的键
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < 26; i++) {
                if (counts[i] != 0) {
                    sb.append((char) ('a' + i));
                    sb.append(counts[i]);
                }
            }
            String key = sb.toString();
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            list.add(str);
            map.put(key, list);
        }
        return new ArrayList<List<String>>(map.values());
    }
}

时空复杂度

方法一:
在这里插入图片描述
​方法二:
在这里插入图片描述

备注

1.str.toCharArray(); 字符串转字符数组
2.Arrays.sort(array); 数组排序
3.map.values(); 获取map里所有的value list
4.map.getOrDefault(key,default_value) ; 获取key的value,没查到返回默认值
5.方法一用java的stream实现

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        return new ArrayList<>(Arrays.stream(strs)
            .collect(Collectors.groupingBy(str -> {
                // 返回 str 排序后的结果。
                // 按排序后的结果来grouping by,类似于 sql 里的 group by。返回的是一个 Map<String, List<String>>,我们只需要取出这个map里的value list就好。用map.values();
                char[] array = str.toCharArray();
                Arrays.sort(array);
                return new String(array);
            })).values());
    }
}

1288. 删除被覆盖区间

https://leetcode-cn.com/problems/remove-covered-intervals/
在这里插入图片描述

思路

数字题,没头绪可以先排序试试,看有没有规律。
这道题按start升序,end降序排序,有三种情况。
在这里插入图片描述
对于这三种情况,我们应该这样处理:

对于情况一,找到了覆盖区间,结果+1。

对于情况二,两个区间可以合并成一个大区间。扩大end边界。

对于情况三,两个区间完全不相交。更新start和end。

代码

class Solution {
    public int removeCoveredIntervals(int[][] intervals) {
        // 按照起点升序排列,起点相同时降序排列
        Arrays.sort(intervals, (a, b) -> {
            if (a[0] == b[0]) {
                return b[1] - a[1];
            }
            return a[0] - b[0]; 
        });
        // 记录合并区间的起点和终点
        int start = intervals[0][0];
        int end = intervals[0][1];

        int res = 0;
        for (int i = 1; i < intervals.length; i++) {
            int[] intv = intervals[i];
            // 情况一,找到覆盖区间
            if (start <= intv[0] && end >= intv[1]) {
                res++;
            }
            // 情况二,找到相交区间,合并
            if (end >= intv[0] && end <= intv[1]) {
                end = intv[1];
            }
            // 情况三,完全不相交,更新起点和终点
            if (end < intv[0]) {
                start = intv[0];
                end = intv[1];
            }
        }
        return intervals.length - res;
        }
}

时空复杂度

1.时间复杂度
O(NlogN)。排序过程O(NlogN),解析排序后的输入数据花费O(N)
2.空间复杂度
O(logN),其中 N 为区间的数量,O(logN) 为排序所需要的空间复杂度。

备注

1.数组的第一个元素升序,第二个元素降序

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

2.思路
数字题,范围题,没有头绪就先排序找规律试试。

56. 合并区间

https://leetcode-cn.com/problems/merge-intervals/
在这里插入图片描述

思路

和上一题思路类似,按start升序排序,如果下一个区间的start<=上一个区间的end,就将两个区间合并,end是两个end的最大值【下图情况1和情况2】;如果下一个区间的start>上一个区间的end,将上一个区间放入结果集,处理下一个待合并区间。
在这里插入图片描述

代码

class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals.length == 0) {
            return new int[0][2];
        }
        //排序
        Arrays.sort(intervals,(a,b)->{
            return a[0]-b[0];
        });
        //结果集
        List<int[]> res = new ArrayList<>();
        //合并区间
        for(int i = 0;i<intervals.length;i++){
            int l = intervals[i][0];
            int r = intervals[i][1];
            if (res.size() == 0 || l > res.get(res.size() - 1)[1]) {
                res.add(new int[]{l, r});
            } else {
                res.get(res.size() - 1)[1] = Math.max(res.get(res.size() - 1)[1], r);
            }
        }
        return res.toArray(new int[res.size()][]);
    }
}

时空复杂度

1.时间复杂度
O(NlogN)。排序过程O(NlogN),解析排序后的输入数据花费O(N)
2.空间复杂度
O(logN),其中 N 为区间的数量,O(logN) 为排序所需要的空间复杂度。

备注

1.list转数组
res.toArray(new int[res.size()][]);

986. 区间列表的交集

https://leetcode-cn.com/problems/interval-list-intersections/
在这里插入图片描述

思路

1.我们用 [a1, a2] 和 [b1, b2] 表示在 A 和 B 中的两个区间,如果这两个区间有交集,需满足 b2 >= a1 && a2 >= b1,分下面四种情况:
在这里插入图片描述
可以发现规律,假设交集区间是 [c1, c2],那么 c1 = max(a1, b1), c2 = min(a2, b2)
2.什么时候换到下一区间?
如果b2 < a2, B的指针走向下一个元素,否则A的指针走向下一个元素

代码

class Solution {
    public int[][] intervalIntersection(int[][] A, int[][] B) {
        List<int[]> res = new LinkedList<>();
        int i = 0, j = 0;
        while (i < A.length && j < B.length) {
            int a1 = A[i][0], a2 = A[i][1];
            int b1 = B[j][0], b2 = B[j][1];

            if (b2 >= a1 && a2 >= b1) {
                res.add(new int[]{
                        Math.max(a1, b1), Math.min(a2, b2)
                });
            }
            if (b2 < a2) {
                j++;
            } else {
                i++;
            }
        }
        return res.toArray(new int[0][0]);
    }
}

时空复杂度

1.时间复杂度
O(M+N),其中M,N 分别是数组 A 和 B 的长度。
2.空间复杂度
O(M+N),答案中区间数量的上限。

备注

1.元素是数组的list
List<int[]> res = new LinkedList<>();

最后

以上就是过时豌豆为你收集整理的力扣每日练习-java版(五)31. 下一个排列49. 字母异位词分组1288. 删除被覆盖区间56. 合并区间986. 区间列表的交集的全部内容,希望文章能够帮你解决力扣每日练习-java版(五)31. 下一个排列49. 字母异位词分组1288. 删除被覆盖区间56. 合并区间986. 区间列表的交集所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部