力扣49题:字母异位词分词(JAVA)

题目描述:

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

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

思路:

1、在使用 HashMap 的基础上,判断两个字符串到底是不是属于字母异位词
2、如果该字符串数组不为空,就在开始时把第一个字符串加入结果集合 List<List> result
3、遍历字符串数组后面的所有字符串,与结果集合中的进行对比,如果相同就直接放入,不相同就开一个新的集合
放入 List< String> res
4、根据力扣的结果测试用例逐步完善算法,比如 “” 的存在以及它的多次存在等;

下面附上我的代码:

IDEA可以跑出来的,带注解:

public class LC49_2_selfAC {
    public static void main(String[] args) {
        String[] strs = {"tea","","eat","","tla",""};
//        String[] strs = {"stop","pots","reed","","tops","deer","opts",""};
//        String[] strs = {"ddddddddddg","dgggggggggg"};
//        String[] strs = {"eat","tea","tan","ate","nat","bat"};
        List<List<String>> result = new ArrayList<>();
        HashMap<Character,Character> map = new HashMap<>();
        int n = strs.length;
        List<String> res = new ArrayList<>();
        // 考虑列表字符串到底是否空。首先把第一个字符串放进去,用后面的和它比;
        res.add(strs[0]);
        result.add(res);
        int flag = 0;
        int idex = 0;
        for (int i = 1; i < n; i++) {
            // 定位获取列表字符串的每一个字符串
            String str = strs[i];
            for (int j = 0; j < result.size(); j++) {
                // 如果相同,证明它们属于一个集合,装进去就行
                String mod = result.get(j).get(0);
                boolean isSame = makeSureSame(str,mod);
                // 细节:每个集合的都是一个相同的字符个数集合,所以只用取第一个来比较
                if(isSame){
                    result.get(j).add(str);
                    break;
                }else{
                    // 如果不相同,后续继续判断
                    // 在这里也细分了到底是不是最后一个集合
                    if(j == result.size()-1){
                        // 这是最后一个可以比较的集合
                        List<String> ress = new ArrayList<>();
                        if(str.equals("")){
                            ress.add("!1");
                            result.add(ress);
                            idex = result.size()-1;
                            flag = 1;
                        }else{
                            // 不是空字符串,前面已经对比出了不属于已有集合,所以直接加到一个新集合
                            ress.add(str);
                            result.add(ress);
                        }
                        break;
                    }
                    // 以下的试用于目前的判断还没走到结果集合的最后一个
                    else if(str=="" && flag == 0){
                        List<String> ress = new ArrayList<>();
                        // 这里把第一个字符串“”存了起来
                        ress.add("!2");
                        result.add(ress);
                        idex = result.size()-1;
                        flag = 1;
                        break;
                    }else if(str.equals("")){
                        //这里是字符串本身为空
                        result.get(idex).add("?3");
                        break;
                    }
                }
            }
        }

        for (int i = 0; i < result.size(); i++) {
            List<String> rest = result.get(i);
            for (int j = 0; j < rest.size(); j++) {
                System.out.print(rest.get(j)+"  ");
            }
            System.out.println();
        }
    }

    public static boolean makeSureSame(String s1,String s2){
        // 用hash存每个字母,先加进去字符和出现次数,再用另一个字符串的来检查,来减少次数,
        // 最终为 0 就表示相同
        // 其中要考虑一些条件
        boolean res = true;
        if(s1.length()!=s2.length()) return false;

        HashMap<Character,Integer> hashMap = new HashMap<>();
        for (int i = 0; i < s1.length(); i++) {
            if(hashMap.containsKey(s1.charAt(i))){
                int times = hashMap.get(s1.charAt(i));
                hashMap.put(s1.charAt(i),times+1);
            }else{
                hashMap.put(s1.charAt(i),1);
            }
        }

        for (int i = 0; i < s2.length(); i++) {
            if(hashMap.containsKey(s2.charAt(i))){
                int times = hashMap.get(s2.charAt(i));
                hashMap.put(s2.charAt(i),times-1);
                if(times-1 == 0){
                    hashMap.remove(s2.charAt(i));
                }
            }else{
                res = false;
                break;
            }
        }
        if(hashMap.isEmpty()){
            res = true;
        }else{
            res = false;
        }
        return res;
    }
}

下面是力扣可以通过的版本:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> result = new ArrayList<>();
        HashMap<Character,Character> map = new HashMap<>();
        int n = strs.length;
        if (strs.length == 0) return result;
        List<String> res = new ArrayList<>();
        res.add(strs[0]);
        result.add(res);
        int flagg = 0;
        int idex = 0;
        for (int i = 1; i < n; i++) {
            String str = strs[i];
            for (int j = 0; j < result.size(); j++) {
                String mod = result.get(j).get(0);
                boolean isSame = makeSureSame(str,mod);
                if(isSame){
                    result.get(j).add(str);
                    break;
                }else{
                    List<String> ress = new ArrayList<>();
                    if(j == result.size()-1){                    
                        if(str.equals("")){
                            ress.add("");
                            result.add(new ArrayList<>(ress));
                            idex = result.size()-1;
                            flagg = 1;
                        }else{
                            ress.add(str);
                            result.add(ress);
                        }
                        break;
                    }
                    else if(str.equals("") && flagg == 0){
                        ress.add("");
                        result.add(new ArrayList<>(ress));
                        idex = result.size()-1;
                        flagg = 1;
                        break;
                    }else if(str.equals("")){
                        result.get(idex).add("");
                        break;
                    }
                }
            }
        }
        return result;
    }

    public boolean makeSureSame(String s1,String s2){
        boolean res = true;
        if(s1.length()!=s2.length()) return false;

        HashMap<Character,Integer> hashMap = new HashMap<>();
        for (int i = 0; i < s1.length(); i++) {
            if(hashMap.containsKey(s1.charAt(i))){
                int times = hashMap.get(s1.charAt(i));
                hashMap.put(s1.charAt(i),times+1);
            }else{
                hashMap.put(s1.charAt(i),1);
            }

        }

        for (int i = 0; i < s2.length(); i++) {
            if(hashMap.containsKey(s2.charAt(i))){
                int times = hashMap.get(s2.charAt(i));
                hashMap.put(s2.charAt(i),times-1);
                if(times-1 == 0){
                    hashMap.remove(s2.charAt(i));
                }
            }else{
                res = false;
                break;
            }
        }
        if(hashMap.isEmpty()){
            res = true;
        }else{
            res = false;
        }

        return res;
    }
}
LeetCode 上,第 100 是“相同的树”(Same Tree),而“字母异位词分组”是 LeetCode49 [^1]。因此,可能存在对号的混淆。下面将分别讨论这两道的相关解法和背景。 ### 1. LeetCode49 字母异位词分组(Group Anagrams) **目描述** 给定一个字符串数组,将所有字母异位词(anagram)组合在一起。字母异位词是指由相同字母不同顺序构成的字符串。 **解法思路** 解决该问的核心思想是:**字母异位词在排序后具有相同的字符串形式**。因此,可以利用哈希表(Map)来将相同排序后的字符串作为键,对应的原始字符串列表作为值。 #### Java 解法示例(排序 + 哈希表) ```java class Solution { public List<List<String>> groupAnagrams(String[] strs) { Map<String, List<String>> map = new HashMap<>(); for (String str : strs) { char[] arr = str.toCharArray(); Arrays.sort(arr); String key = new String(arr); List<String> list = map.getOrDefault(key, new ArrayList<>()); list.add(str); map.put(key, list); } return new ArrayList<>(map.values()); } } ``` #### Java 解法示例(计数 + 哈希表) 该方法适用于字符集较大的情况,例如 Unicode 字符。它基于字符出现的频率构建键值。 ```java public List<List<String>> groupAnagrams(String[] strs) { Map<String, List<String>> map = new HashMap<>(); for (String str : strs) { int[] count = new int[26]; for (char c : str.toCharArray()) { count[c - 'a']++; } StringBuilder key = new StringBuilder(); for (int i = 0; i < 26; i++) { key.append(count[i]).append('#'); } String keyStr = key.toString(); if (!map.containsKey(keyStr)) { map.put(keyStr, new ArrayList<>()); } map.get(keyStr).add(str); } return new ArrayList<>(map.values()); } ``` **时间复杂度分析** - 排序法:O(n * k log k),其中 `n` 是字符串数量,`k` 是字符串的最大长度。 - 计数法:O(n * k),其中 `k` 是字符串的平均长度,适用于较长字符串的情况。 **空间复杂度** - O(n * k),用于存储哈希表中的键值对。 ### 2. LeetCode 第 100 :相同的树(Same Tree) **目描述** 给定两棵二叉树,判断它们是否相同。两棵树相同当且仅当它们的结构相同,并且每个节点的值也相同。 **解法思路** 可以通过递归或迭代的方式比较两棵树的每个节点: - 如果当前节点都为空,则相同。 - 如果一个为空而另一个非空,则不相同。 - 如果节点值不同,则不相同。 - 否则递归比较左右子树。 #### Java 解法示例(递归) ```java public boolean isSameTree(TreeNode p, TreeNode q) { if (p == null && q == null) return true; if (p == null || q == null) return false; return p.val == q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right); } ``` #### Java 解法示例(迭代,使用队列) ```java public boolean isSameTree(TreeNode p, TreeNode q) { Queue<TreeNode> queue = new LinkedList<>(); queue.offer(p); queue.offer(q); while (!queue.isEmpty()) { TreeNode node1 = queue.poll(); TreeNode node2 = queue.poll(); if (node1 == null && node2 == null) continue; if (node1 == null || node2 == null || node1.val != node2.val) return false; queue.offer(node1.left); queue.offer(node2.left); queue.offer(node1.right); queue.offer(node2.right); } return true; } ``` **时间复杂度** - O(n),其中 `n` 是树的节点数。 **空间复杂度** - 最坏情况下为 O(n),取决于树的高度。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值