每日算法题-字母异位词分组&最长连续序列

81 阅读2分钟

leetcode链接

字母异位词分组:leetcode.cn/problems/gr…

最长连续序列:leetcode.cn/problems/lo…

字母异位词分组

这题的题目描述让人很难理解,但是其实所谓的字母异位词就是指包含字母相同但是字母顺序不同的字符串,比如abc和cba,理解了意思这道题就很好做了。 可以通过Map对字符进行分组,对于一个字母异位词,他有以下特点:

  1. 包含的字母相同
  2. 字母出现的次数相同
  3. 字母的顺序不同

如果我们找到他们共有特点组成的key就能完成对他们的分组,题目中有提到字母都是小写字母,这很关键,意味着我们可以使用字母的asscii值,而且所有源单词中的字母通常恰好只用一次意味着我们不需要考虑重复的场景,有些人可能想到是不是能用字符的和作为key,但是这其实是不行的,虽然字母异位置词的和确实相同,但是也可能出现相撞的情况,比如bf和ce,这是他们对应的asscii值b:98,c:99,e:101,f:102,此时可以发现对于出现次数我们并没有很好的利用,其实我们可以利用出现次数与字母一起组成key比如a1b1c1,这样就达到了分组的目的,下面是代码实现:

public List<List<String>> groupAnagrams(String[] strs) {
    List<List<String>> result = new ArrayList<>();
    Map<String, List<String>> map = new HashMap<>();
    //遍历字符串分组
    for (String str : strs) {
        int[] nums = new int[26];
        for (int i = 0; i < str.length(); i++) {
            nums[str.charAt(i) - 'a']++;
        }
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 26; i++) {
            if (nums[i] != 0) {
                builder.append((char) 'a' + i);
                builder.append(nums[i]);
            }
        }
        String key = builder.toString();
        List<String> value = map.getOrDefault(key, new ArrayList<>());
        value.add(str);
        map.put(key, value);
    }
    //打印结果
    for (Map.Entry<String, List<String>> entry : map.entrySet()) {
        result.add(entry.getValue());
    }
    return result;
}

最长连续序列

这道题,很容易想到排序,在有序之后对连续的数字进行统计,当然要注意相同数字的情况跳过处理,那么代码如下:

public int longestConsecutive(int[] nums) {
    if (nums == null || nums.length == 0) {
        return 0;
    }
    Arrays.sort(nums);
    int result = Integer.MIN_VALUE;
    int size = 0;
    for (int i = 1; i < nums.length; i++) {
        if (nums[i] == (nums[i - 1] + 1)) {
            size++;
            result = Math.max(size, result);
        } else {
            size = 0;
        }
    }
    return result == Integer.MIN_VALUE ? 0 : result + 1;
}

用排序的方式解决之后我又去看了看官网的题解,看到了hash的解法,将数组内容提前存入hash中,然后确定起点向后查找统计最大长度,代码如下:

public int longestConsecutive(int[] nums) {
    Set<Integer> list = new HashSet<>();
    for (int num : nums) {
        list.add(num);
    }

    int result = 0;
    for (int num : nums) {
        //判断是否是起点
        if (!list.contains(num - 1)) {
            int currentNum = num;
            int temp = 0;
            while (list.contains(currentNum++)) {
                temp++;
            }
            result = Math.max(result, temp);
        }
    }
    return result;
}

这两种方式比较起来,排序的方式时间复杂度是O(n),空间复杂度O(1)。hash法除了O(n)的时间复杂度之外,还有O(n)的空间复杂度。