Leet Code Hot100 刷题记录

文章介绍了如何使用HashMap和HashSet等数据结构解决字符串相关问题,如字母异位词分组、最长连续序列查找、移动数组中的零以及求解盛最多水的容器问题,强调了算法效率和数据结构在这些问题中的关键作用。
摘要由CSDN通过智能技术生成

1. 字母异位词分组(HashMap)

题目:

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

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

题解:

  1. 初始化一个空的 HashMap map。
  2. 遍历字符串数组 strs。
  3. 对第一个字符串 "eat"执行:将 "eat" 转换为字符数组 ['e', 'a', 't'] 对字符数组进行排序,得到 ['a', 'e', 't']
  4. 使用排序后的字符数组创建 key "aet" 从 map 中获取 key 为 "aet" 的值,由于不存在,因此创建一个新的空列表 list = [] 将 "eat" 添加到 list 中,现在 list = ["eat"] 将 key 为 "aet",value 为 ["eat"] 的键值对存入 map。
  5. 对第二个字符串 "tea" 执行类似操作: 字符数组为 ['t', 'e', 'a'],排序后为 ['a', 'e', 't'],key 为 "aet" 从 map 中获取 key 为 "aet" 的值,存在,为 ["eat"] 将 "tea" 添加到列表中,现在列表为 ["eat", "tea"] 将更新后的列表存入 map,key 为 "aet" 对其余字符串 "tan", "ate", "nat", "bat" 执行类似操作,最终 map 为: key 为 "aet",value 为 ["eat", "tea", "ate"] key 为 "ant",value 为 ["tan", "nat"] key 为 "abt",value 为 ["bat"]
  6. 从 map 中获取所有 value,构造结果列表,即 [ ["eat", "tea", "ate"], ["tan", "nat"], ["bat"] ]
  7. 可以看到,通过将每个字符串排序作为 key,并存储字母异位词的字符串列表作为 value,算法成功将字母异位词分组了。
  8. 这样的分组过程更加高效,避免了对每个字符串都进行两两比较的低效操作。

 代码实现:

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());
    }
}

总结:利用HashMap中元素的唯一性,来进行两个字符串是否存在相同元素的判断。

2. 最长连续序列(HashSet)

 题目:

        给定一个未排序的整数数组nums,找出数字连续的最长序列的长度。

        不要求序列元素在原数组中连续,并且算法时间复杂度为O(n)。

题解:

  1. 首先利用HashSet集合对数组进行去重,减少重复比较
  2. for循环遍历集合中的每个值num,当集合中不存在比该值的小的值,即set.contains(num-1)为false时,记录该元素为currentNum,记录当前连续序列长度currentStreak为1。
  3. 接下来,使用while循环,每次查找比currentNum大1的值是否存在,即判断set.contains(currentNum+1)是true or false,如果是true,则将当前连续序列长度currentStreak加1,并且将当前元素currentNum+1,循环下去直到不满足条件。
  4. while循环结束后,得到以num开头的最长连续序列长度currentStreak,将其与当前最长连续序列长度longestStreak进行比较,取较大的值重新赋值给longestStreak。
  5. for循环遍历结束,返回最终的最长连续序列长度longestStreak。

代码实现:

class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> num_set = new HashSet<Integer>();
        for (int num : nums) {
            num_set.add(num);
        }
        int longestStreak = 0;
        for (int num : num_set) {
            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;
    }
}

总结

  1. 利用HashSet的contains方法,判断某元素是否在集合内,简化比较过程。
  2. 利用判断(num-1)是否在集合内的方法,提前把不可能是连续序列的开头的数据排除了,避免了存在比当前序列更长的序列的情况。

3. 移动零

题目:

        给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。必须在不复制数组的情况下原地对数组进行操作。

代码实现:

class Solution {
    public void moveZeroes(int[] nums) {
        int n = nums.length, left = 0, right = 0;
        while (right < n) {
            if (nums[right] != 0) {
                swap(nums, left, right);
                left++;
            }
            right++;
        }
    }

    public void swap(int[] nums, int left, int right) {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }
}

总结

  1. 利用两个变量作为指针,左指针的作用是找到0,右指针的作用是指向0的后一元素。
  2. 通过左右指针的互换,实现在保持非零元素顺序不变的情况下,将0移到数组末尾。 

4. 盛最多水的容器(双指针)

题目:

  • 给定一个长度为n的整数数组height。
  • 有n条垂线,第i条线的两个端点是(i,0)和(i,height[i])。
  • 找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。
  • 返回容器可以储存的最大水量。

题解:

 

代码实现:(存在超时错误)

class Solution {
    public int maxArea(int[] height) {
        int waterfilling=0; 
        for (int i=0;i<height.length-1;i++){
            int left=i;
            int right=i+1;
            int currentwater=0;
            while(right<height.length){
                currentwater=(right-left)*Math.min(height[left],height[right]);
                if(currentwater>waterfilling){
                    waterfilling=currentwater;
                }
            right++;
            }
        }
    return waterfilling;
    }
}

代码实现:(通过)

class Solution {
    public int maxArea(int[] height) {
        int left=0;
        int right=height.length-1;
        int waterfilling=0;
        int currentwater=0;
        while(true){
            currentwater=(right-left)*Math.min(height[left],height[right]);
            if(currentwater>waterfilling){
                waterfilling=currentwater;
            }
            if(height[left]<height[right]){
               left++ ;
            }else{
                right--;
            }
            if(left==right){
                break;
            }
        }
        return waterfilling;
    }
}

 总结

  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值