Java算法 字母异位词分组 、最长连续序列

小王的Java刷题日记Day5

记录刷题过程,作为笔记和分享,坚持每天刷题,每天进步,编程语言为Java。

题目一:字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

例如:

输入: strs = ["see", "ese", "say", "ees", "asy", "baa"]
输出: [["baa"],["say","asy"],["see","ese","ees"]]

思路:    哈希表存储排序后进行比较                        时间复杂度:O(nklog⁡k)

1、两个字符串互为字母异位词,当且仅当两个字符串包含的字母相同。

2、同一组字母异位词中的字符串具备相同点,可以使用相同点作为一组字母异位词的标志,使用哈希表存储每一组字母异位词,哈希表的键为一组字母异位词的标志,哈希表的值为一组字母异位词列表。

3、遍历每个字符串,对于每个字符串,得到该字符串所在的一组字母异位词的标志,将当前字符串加入该组字母异位词的列表中。遍历全部字符串之后,哈希表中的每个键值对即为一组字母异位词。

4、由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键。

5、具体更加详细的解释已经注解在代码块中。

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        // 创建一个哈希表,键是排序后的字符串,值是原始字符串的列表
        Map<String, List<String>> hashMap = new HashMap<String, List<String>>();
        // 遍历输入的字符串数组
        for (String str : strs) { //循环遍历数组 strs 中的每个元素,将当前元素赋值给变量 str,然后执行循环体内的操作。
            char[] array = str.toCharArray();    // 将字符串转换为字符数组,并对字符数组进行排序
            Arrays.sort(array);
            // 将排序后的字符数组转换为字符串,作为哈希表的键
            String key = new String(array);
            // 获取键对应的值,如果键不存在则创建一个新的空列表
            List<String> list = hashMap.getOrDefault(key, new ArrayList<String>());
            // 将当前字符串添加到列表中
            list.add(str);
            // 更新哈希表中的键值对
            hashMap.put(key, list);
        }
        // 返回哈希表中的值,即每个组中的字符串列表
        return new ArrayList<List<String>>(hashMap.values());
    }
}

注:

时间复杂度:O(nklog⁡k),其中 n 是 strs中的字符串的数量,k 是 strs中的字符串的的最大长度。需要遍历 n个字符串,对于每个字符串,需要 O(klog⁡k)的时间进行排序以及 O(1)的时间更新哈希表,因此总时间复杂度是 O(nklog⁡k)。

题目二:最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。    请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

例如:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

思路: 哈希表

排序的话时间复杂度会超出题目要求,所以考虑哈希表。

1使用 HashSet 存储数组中的元素,以便快速查找

2、记录最长连续序列的长度

3、遍历 HashSet 中的每个元素,如果当前元素的前一个元素不在 HashSet 中,说明当前元素是一个连续序列的起始点。

4、继续向后查找,直到不再连续为止

5、更新最长连续序列的长度

6、返回最长连续序列的长度

public class Solution {
    // 找出数组中最长的连续序列的长度
    public int longestConsecutive(int[] nums) {
        // 使用 HashSet 存储数组中的元素,以便快速查找
        Set<Integer> num_set = new HashSet<Integer>();
        for (int num : nums) {
            num_set.add(num);
        }

        // 记录最长连续序列的长度
        int longestStreak = 0;

        // 遍历 HashSet 中的每个元素
        for (int num : num_set) {
            // 如果当前元素的前一个元素不在 HashSet 中,说明当前元素是一个连续序列的起始点
            if (!num_set.contains(num - 1)) {
                int currentNum = num;
                int currentStreak = 1;

                // 继续向后查找,直到不再连续为止
                while (num_set.contains(currentNum + 1)) {
                    currentNum += 1;
                    currentStreak += 1;
                }

                // 更新最长连续序列的长度
                longestStreak = Math.max(longestStreak, currentStreak);
            }
        }

        // 返回最长连续序列的长度
        return longestStreak;

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
算法设计: 1. 定义一个哈希表,键为排序后的字符串,值为原始字符串的数组列表。 2. 遍历字符串数组,对于每个字符串,将其排序并存储在一个临时变量中。 3. 如果哈希表中已经存在这个排序后的字符串,则将原始字符串添加到相应的值数组中。否则,将排序后的字符串作为新键,原始字符串作为值数组的第一个元素添加到哈希表中。 4. 将哈希表中的所有值数组添加到结果列表中。 Java 代码实现与验证: ```java class Solution { public List<List<String>> groupAnagrams(String[] strs) { Map<String, List<String>> map = new HashMap<>(); for (String str : strs) { char[] chars = str.toCharArray(); Arrays.sort(chars); String key = new String(chars); if (!map.containsKey(key)) { map.put(key, new ArrayList<>()); } map.get(key).add(str); } return new ArrayList<>(map.values()); } } ``` 我们可以使用 Junit 等单元测试框架对该算法进行验证,以确保其正确性和鲁棒性。 ```java class SolutionTest { @Test void testGroupAnagrams() { Solution solution = new Solution(); String[] strs = {"eat", "tea", "tan", "ate", "nat", "bat"}; List<List<String>> expected = new ArrayList<>(); expected.add(Arrays.asList("ate", "eat", "tea")); expected.add(Arrays.asList("nat", "tan")); expected.add(Arrays.asList("bat")); List<List<String>> result = solution.groupAnagrams(strs); assertEquals(expected.size(), result.size()); for (int i = 0; i < expected.size(); i++) { Collections.sort(expected.get(i)); Collections.sort(result.get(i)); assertEquals(expected.get(i), result.get(i)); } } } ``` 以上代码使用 Junit 框架对 `groupAnagrams()` 方法进行测试,测试数据为 `{"eat", "tea", "tan", "ate", "nat", "bat"}`,期望的输出结果是 `[[ate, eat, tea], [nat, tan], [bat]]`。在测试中,我们首先通过 `assertEquals()` 方法比较了期望输出和实际输出的组数是否相等,如果相等,则分别对每个组进行排序,并通过 `assertEquals()` 方法比较期望输出和实际输出是否相等。 测试结果表明,该算法的输出结果与期望结果相同,因此该算法的正确性和鲁棒性得到验证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值