【LeetCode】 移除字母异位词后的结果数组Java题解

92 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

题目描述

给你一个下标从 0 开始的字符串 words ,其中 words[i] 由小写英文字符组成。

在一步操作中,需要选出任一下标 i ,从 words 中 删除 words[i] 。其中下标 i 需要同时满足下述两个条件:

0 < i < words.length words[i - 1] 和 words[i] 是 字母异位词 。 只要可以选出满足条件的下标,就一直执行这个操作。

在执行所有操作后,返回 words 。可以证明,按任意顺序为每步操作选择下标都会得到相同的结果。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。例如,"dacb" 是 "abdc" 的一个字母异位词。


示例 1:

输入:words = ["abba","baba","bbaa","cd","cd"]
输出:["abba","cd"]
解释:
获取结果数组的方法之一是执行下述步骤:
- 由于 words[2] = "bbaa" 和 words[1] = "baba" 是字母异位词,选择下标 2 并删除 words[2] 。
  现在 words = ["abba","baba","cd","cd"]- 由于 words[1] = "baba" 和 words[0] = "abba" 是字母异位词,选择下标 1 并删除 words[1] 。
  现在 words = ["abba","cd","cd"]- 由于 words[2] = "cd" 和 words[1] = "cd" 是字母异位词,选择下标 2 并删除 words[2] 。
  现在 words = ["abba","cd"] 。
无法再执行任何操作,所以 ["abba","cd"] 是最终答案。

示例 2:

输入:words = ["a","b","c","d","e"]
输出:["a","b","c","d","e"]
解释:
words 中不存在互为字母异位词的两个相邻字符串,所以无需执行任何操作。


来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-resultant-array-after-removing-anagrams
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析

  • 今天的算法题目是数组处理题目,题目比较长,分析重点如下。1. 求字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次,这里需要注意的是,两个单词完全相同也是异位词。2. 当连续的两个单词是异位词的时候,删除前一个。
  • 根据如上分析,我们首先实现字母异位词的代码判断,判断的时候,由于都是小写字母,我们可以使用ASCII知识。什么是 ASCII?ASCII 码是一套编码规范,其中97~122号为26个小写英文字母。用数组记录字符出现的次数。遍历过后,当数组出现次数都是 0 的时候,两个单词即为字母异位词。
  • 做这个题目时候,通过观察,字母异位词可以传递,因此,我们只保留当前的单词即可。这一步很重要,不容易想到,我也是参考题解才学会的,需要好好思考。具体实现代码如下,供参考。

通过代码

class Solution {
    public List<String> removeAnagrams(String[] words) {
        List<String> ans = new ArrayList<>();
        int n = words.length;
        ans.add(words[0]);
        for (int i = 1; i < n; i++) {
            if (check(words[i - 1], words[i])){ 
                continue;
            }
            ans.add(words[i]);
        }

        return ans;
    }

    private boolean check(String word1, String word2) {
        boolean ans = false;
        if (word1.equals(word2)) {
            ans = true;
            return ans;
        }
        int n1 = word1.length();
        int n2 = word2.length();
        if (n1 != n2) {
            return ans;
        }
        int n = 26;
        int[] cnt = new int[n];
        for (int j = 0; j < n1; j++) {
            cnt[word1.charAt(j) - 'a']++;
            cnt[word2.charAt(j) - 'a']--;
        }

        for (int k = 0; k < n; k++) {
            if (cnt[k] != 0) {
                return ans;
            }
        }
        ans = true;
        return ans;
    }

}

总结

  • 上述算法的时间复杂度是O(n),空间复杂度是O(n)
  • 坚持算法每日一题,加油!