Leecode Hot25

哈希

Solution1 两数之和

在这里插入图片描述

数组{2, 11, 15, 7},找数组里面和为9的两个数
思路:
①把{2, 11, 15, 7}转为map,map的key就是存储数组中的值,value就是存储数组中对应的索引,得到的map就是<<2,0> , <11,1> , <15,2> ,<7,3>>
②遍历{2, 11, 15, 7},遍历到2时,9-2=7,检查一下7是否在map中,如果map中有7那么说明数组{2, 11, 15, 7}中第0条和第3条数据之和为9

import java.util.HashMap;
import java.util.Map;

public class TwoSum {
   
    public int[] twoSum(int[] nums, int target) {
   
        // 创建一个哈希表来存储数组中的值和对应的索引
        Map<Integer, Integer> map = new HashMap<>();
        
        // 遍历数组中的每个元素
        for (int i = 0; i < nums.length; i++) {
   
            int complement = target - nums[i]; // 计算当前元素需要的配对值
            
            // 检查哈希表中是否包含需要的配对值
            if (map.containsKey(complement)) {
   
                // 如果包含,则返回当前元素的索引和配对值的索引
                return new int[] {
    map.get(complement), i };
            }
            
            // 如果不包含,则将当前元素的值和索引存入哈希表
            map.put(nums[i], i);
        }
        
        // 如果没有找到任何结果,则抛出一个异常(根据题目描述,这种情况不会发生)
        throw new IllegalArgumentException("No two sum solution");
    }

    public static void main(String[] args) {
   
        TwoSum solution = new TwoSum();
        int[] nums = {
   2, 7, 11, 15};
        int target = 9;
        int[] result = solution.twoSum(nums, target);
        
        // 输出结果
        System.out.println("Indices: [" + result[0] + ", " + result[1] + "]");
    }
}

Solution49 字母异位词分组

这里是引用

字母异位词是指由相同字母组成但排列不同的字符串,例如 “eat"和"ate” 就是字母异位词。

解决思路:
①"eat", “tea”, “ate"是字母字母异位词,他们的共同特点是对它们排序后值相等都是"aet”,所以我们用一个Map<String, List>存放结果,map的key就是排序后的内容"aet",value就是[“eat”, “tea”, “ate”]
②遍历字符串数组,对于每个字符串(如"tea"),将其转换为字符数组(如[“t”,“e”,“a”]),然后排序(如[“a”,“e”,“t”]),将排序后的字符数组转换回字符串(如"aet"),作为哈希表的键,往map里面放即可
③如{"eat", "tea", "tan", "ate", "nat", "bat"}数组对应的map就是

{
    "aet":["eat","tea","ate"],
    "abt":["abt"],
    "ant":["tan","nat"]

}
public class Solution {
   
    
    public List<List<String>> groupAnagrams(String[] strs) {
   
        // key是"eat", "tea", "ate"是字母字母异位词,他们的共同特点是对它们排序后值相等都是"aet"
        // map的key就是排序后的内容,value就是["eat", "tea", "ate"]
        Map<String, List<String>> map = new HashMap<>();
        
        for (String str : strs) {
   
            // 将字符串转换为字符数组,然后排序
            char[] chars = str.toCharArray();
            Arrays.sort(chars);
            // 将排序后的字符数组转换回字符串,作为哈希表的键
            String sortedStr = new String(chars);

            // 检查哈希表中是否已包含该键
            if (!map.containsKey(sortedStr)) {
   
                // 如果不包含,则创建一个新的列表来存储字母异位词
                map.put(sortedStr, new ArrayList<>());
            }
            // 将当前字符串添加到对应的列表中
            map.get(sortedStr).add(str);
        }

        // 返回哈希表中所有值的列表(即字母异位词组)
        return new ArrayList<>(map.values());
    }

    public static void main(String[] args) {
   
        Solution solution = new Solution();
        String[] strs = {
   "eat", "tea", "tan", "ate", "nat", "bat"};
        List<List<String>> result = solution.groupAnagrams(strs);

        // 输出结果
        for (List<String> group : result) {
   
            System.out.println(group);
        }
    }
}

Solution128 最长连续序列

这里是引用

思路:
把数组{1,100, 4, 3, 2, 200}放到set里面去重,然后遍历set里面的每一个值:

  • 当前值为1,我看看set里面是否包含2,包含;那我继续看看set里面是否包含3,包含;那我继续看看set里面是否包含4,包含;那我看看set里面是否包含5,不包含;那么当值为1时最长序列为4
  • 当前值为100,我看看set里面是否包含101,不包含;那么当值为100时最长序列为1
  • 当前值为4,我看看set里面是否包含5,不包含;那么当值为4时最长序列为1
  • 当前值为3,我看看set里面是否包含4,包含;那我看看set里面是否包含5,不包含;那么当值为3时最长序列为2
  • 其实你看到当值为3时,我看看2是否在set里面,如果2在set里面我就跳过,我就不计算3了,因为从2计算的时候肯定比从3计算出来的最长序列要大
public class Solution {
   

    public int longestConsecutive(int[] nums) {
   
        if (nums == null || nums.length == 0) {
   
            return 0;
        }

        Set<Integer> numSet = new HashSet<>();
        for (int num : nums) {
   
            numSet.add(num);
        }

        int longestStreak = 0;

        for (int num : numSet) {
   
            if (!numSet.contains(num - 1)) {
   
                int currentNum = num;
                int currentStreak = 1;

                while (numSet.contains(currentNum + 1)) {
   
                    currentNum += 1;
                    currentStreak += 1;
                }

                longestStreak = Math.max(longestStreak, currentStreak);
            }
        }

        return longestStreak;
    }

    public static void main(String[] args) {
   
        Solution solution = new Solution();
        int[] nums = {
   1,100, 4, 3, 2, 200};
        System.out.println("Longest consecutive sequence length: " + solution.longestConsecutive(nums)); // Output: 4
    }
}

双指针

Solution283 移动零

这里是引用

两个人一起往后走,遇到了一个0,我站在这里不动,你继续往后走;
你往后走的时候遇到了一个非0的数,你把那个数挪过来放到我站的这里,然后我往后走一步,你也继续往后走

思路:
第一次遍历:从index=0开始遍历数组,如果当前元素不是0,则将其放到index指定的位置,并递增index。
第二次遍历:从index开始,将剩余的位置全部填充为0。

public class Solution {
   
    
    public void moveZeroes(int[] nums) {
   
        int n = nums.length; // 数组的长度
        int index = 0; // 用于记录非零元素应该存放的位置

        // 遍历数组,将所有非零元素按顺序移动到数组前面
        for (int i = 0; i < n; i++) {
   
            if (nums[i] != 0) {
   
                nums[index] = nums[i]; // 将非零元素放到正确的位置
                index++; // 更新非零元素应该存放的位置
            }
        }

        // 将剩余的位置填充为0
        for (int i = index; i < n; i++) {
   
            nums[i] = 0;
        }
    }

    public static void main(String[] args) {
   
        Solution mz = new Solution();
        int[] nums = {
   0, 1, 0, 3, 12};

        System.out.println("原始数组:");
        for (int num : nums) {
   
            System.out.print(num + " ");
        }
        System.out.println();

        mz.moveZeroes(nums);

        System.out.println("移动0后的数组:");
        for (int num : nums) {
   
            System.out.print(num + " ");
        }
    }
}

Solution11 盛最多水的容器

这里是引用

思路:

  • maxArea用于存储最大水量。
    left:指向数组的第一个元素
    right:指向数组的最后一个元素
  • while (left < right)时循环执行下面逻辑:
    计算当前左右指针构成的容器的面积,并更新最大面积。
    如果height[left] < height[right],那么left++,否则right–(移动高度较小的指针,因为移动高度较大的指针不会得到更大的面积)
public class Solution {
   

    public int maxArea(int[] height) {
   
        if (height == null || height.length < 2) {
   
            throw new IllegalArgumentException("数组长度必须至少为2");
        }

        int maxArea = 0;
        int left = 0; // 左指针
        int right = height.length - 1; // 右指针

        while (left < right) {
   
            // 计算当前左右指针构成的容器的面积
            int currentArea = Math.min(height[left], height[right]) * (right - left);
            // 更新最大面积
            maxArea = Math.max(maxArea, currentArea);

            // 移动指针的策略:移动高度较小的指针,因为移动高度较大的指针不会得到更大的面积
            if (height[left] < height[right]) {
   
                left++;
            } else {
   
                right--;
            }
        }

        return maxArea;
    }

    public static void main(String[] args) {
   
        Solution solution = new Solution();
        int[] height = {
   1, 8, 6, 2, 5, 4, 8, 3, 7};
        int maxWater = solution.maxArea(height);
        System.out.println("容器可以储存的最大水量是: " + maxWater);
    }
}

Solution15 三数之和

这里是引用

思路:

现在,我们带入数组{-1, 0, 1, 2, -1, -4}来详细说明处理过程。

  1. 排序:排序后的数组为:[-4, -1, -1, 0, 1, 2]

  2. 遍历数组:我们从索引0开始遍历,直到nums.length - 3,即索引3

  3. 固定元素并寻找双指针

    当i = 0时,固定元素为-4,left = 1,right = 5

    • 计算和:-4 + (-1) + 2 = -3(sum<0,left++
    • 计算和:-4 + 0 + 2 = -2sum < 0,所以left++
    • 计算和:-4 + 1 + 2 = -1sum < 0,但此时left已经等于right - 1,所以无法再增加left,结束循环)
    • 此时leftright相遇,结束循环。

    i = 1时,固定元素为-1,left = 2,right = 5

    • 计算和:-1 + (-1) + 2 = 0(sum=0,加入结果集,结果集:[[-1, -1, 2]]left++right--
    • 计算和:-1 + (0) + 1 = 0(sum=0,加入结果集,结果集:[[-1, -1, 2],[-1,0,1]]left++right--
    • 此时leftright相遇,结束循环。

    i = 2时,固定元素为-1,由于-1和前面的元素相等,所以结束循环

    i = 3时,固定元素为0,left = 4,right = 5

    • 计算和:0 + (1) + 2 = 3(sum>0,right–)
    • 此时leftright相遇,结束循环。
public class Solution {
   
    public List<List<Integer>> threeSum(int[] nums) {
   
        List<List<Integer>> result = new ArrayList<>();
        // 先对数组进行排序
        Arrays.sort(nums);

        for (int i = 0; i < nums.length - 2; i++) {
   
            // 跳过重复元素,避免结果中有重复的三元组
            if (i > 0 && nums[i] == nums[i - 1]) {
   
                continue;
            }

            int left = i + 1;
            int right = nums.length - 1;

            while (left < right) {
   
                int
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BlackTurn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值