LeetCode刷题 --- 哈希表

1. 两数之和

解题思路:

  1. 利用哈希表,key存数组当前值,value存数组下标
  2. 两数之和等于target,可以看做是两个数是配对
  3. 遍历数组,看哈希表中有没有值和这个当前值配对,如果没有,就存入哈希表
  4. 如果有,当前数,和配对的数,就是所求值。
    public int[] twoSum(int[] nums, int target) {
        int[] res = {-1, -1};
        Map map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (!map.containsKey(target - nums[i])) {
                map.put(nums[i], i);
                continue;
            }
            res[0] = map.get(target - nums[i]);
            res[1] = i;
            return res;
        }
        return res;
    }

3. 无重复字符的最长子串

解题思路 -- 哈希表

  1. 定义两个指针,分别是左指针和右指针,for循环遍历字符串
  2. 定义一个hashMap存放数据(用于判断重复)
  3. 右指针不断往后遍历
    1. 如果当前元素不存在,就添加到哈希表中,然后继续遍历
    2. 如果当前元素存在,就把左指针更新成哈希表中value的值+1
      1. ----注意这个位置,如果value的值+1 小于当前left,则不需要更新
  4. 每次循环的时候,计算左右指针之差,获取较大的值
    public static int lengthOfLongestSubstring1(String s) {
        byte[] bytes = s.getBytes();
        int res = 0;

        Map map = new HashMap<>();
        int left = 0;
        int right = 0;
        for (; right < bytes.length; right++) {
            if (map.containsKey(bytes[right])) {
                left = Math.max(left, map.get(bytes[right]) + 1);
                map.put(bytes[right], right);
            } else {
                map.put(bytes[right], right);
            }
            res = Math.max(res, right - left + 1);
        }
        return res;
    }

解题思路 --- 滑动窗口

上面是用双指针解题,其实双指针的题目很容易用滑动窗口的模板来套用解题

  1. 外层右指针向右滑动
  2. 内层左指针向右滑动
    public static int lengthOfLongestSubstring(String s) {
        byte[] bytes = s.getBytes();
        int res = 0;

        Set set = new HashSet<>();
        int right = 0;
        int left = 0;
        while (right < bytes.length) {
            while (set.contains(bytes[right])) {
                set.remove(bytes[left]);
                left++;
            }
            res = Math.max(right - left, res);
            set.add(bytes[right]);
            right++;
        }
        return res;
    }

49. 字母异位词分组

解题思路:

看题意,其实就是要把字母相同顺序不同的字符串进行分组。

  1. 先对每个字符串中的字母按照顺序进行排列,得到一个key,这个字符串就作为value中的一个数据
  2. 遍历数组,把所有的字符串都存入到value中
  3. 最后返回map.values()集合即可。
    public List> groupAnagrams(String[] strs) {
        Map> map = new HashMap<>();

        for (String str : strs) {
            String sort = sort(str);
            if (map.containsKey(sort)) {
                List strings = map.get(sort);
                strings.add(str);
                map.put(sort, strings);
            } else {
                ArrayList strings = new ArrayList<>();
                strings.add(str);
                map.put(sort, strings);
            }
        }

        return new ArrayList<>(map.values());
    }

    private static String sort(String str) {
        char[] chars = str.toCharArray();
        Arrays.sort(chars);
        return Arrays.toString(chars);
    }

136. 只出现一次的数字

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

解题1

  1. 数组排序,当前值和后面一个值进行比较,相同则说明有重复的,不同则说明没有重复
  2. 循环遍历,每次i+2;
    public static int singleNumber(int[] nums) {
        Arrays.sort(nums);
        int i = 0;
        while (i < nums.length - 1) {
            if (nums[i] == nums[i + 1]) {
                i = i + 2;
            } else {
                return nums[i];
            }
        }
        // 解决长度仅为1的场景
        return nums[nums.length - 1];
    }

解题2

  1. 做一个set,遍历数组,如果set不存在元素,就存入
  2. 如果存在,就删除元素
  3. 最后剩下的一个,就是只出现一次的数字
    public static int singleNumber3(int[] nums) {
        Set set = new HashSet<>();
        for (int num : nums) {
            if (set.contains(num)) {
                set.remove(num);
            } else {
                set.add(num);
            }
        }

        return  (Integer) set.toArray()[0];
    }

解题3 --- 位运算

LeetCode刷题 --- 哈希表_第1张图片

 LeetCode刷题 --- 哈希表_第2张图片

    public static int singleNumber4(int[] nums) {
        int single = 0;
        for (int num : nums) {
            single = single ^ num;
        }
        return  single;
    }

387. 字符串中的第一个唯一字符

解题思路:

  1. 定义一个map,key存放字符,value存放下标
  2. 遍历字符串,如果map不存在,就存入
  3. 如果map存在,就把value值改为字符串长度
  4. 遍历map的value,每次取value较小的一个值
  5. 如果value等于字符串长度,说明不存在单个字符,返回-1,否则value值就是第一次出现的单个字符。
    public static int firstUniqChar(String s) {
        char[] chars = s.toCharArray();
        Map map = new HashMap<>();
        for (int i = 0; i < chars.length; i++) {
            if (map.containsKey(chars[i])) {
                map.put(chars[i], chars.length);
            } else {
                map.put(chars[i], i);
            }
        }

        int res = s.length();
        for (Integer value : map.values()) {
            res = Math.min(res, value);
        }
        return res == s.length() ? -1 : res;
    }

819. 最常见的单词

对字符串做一个分割,然后遍历,把单词存入到map中,最后取出符合要求的单词即可。

易错点:单词的分割

class Solution {
    public String mostCommonWord(String paragraph, String[] banned) {
        String[] pars = paragraph.split(" |\\!|\\?|\\;|,|\\.|\\'");
        Map map = new HashMap<>();

        for (String par : pars) {
            if (par.equals("")) {
                continue;
            }
            par = par.toLowerCase();
            if (map.containsKey(par)) {
                map.put(par, map.get(par) + 1);
            } else {
                map.put(par, 1);
            }
        }

        Set set = new HashSet<>(Arrays.asList(banned));

        String res = null;
        int value = 0;
        for (Map.Entry entry : map.entrySet()) {
            if (set.contains(entry.getKey())) {
                continue;
            } else {
                if (entry.getValue() > value) {
                    value = entry.getValue();
                    res = entry.getKey();
                }
            }
        }
        return res;
    }
}

你可能感兴趣的:(算法刷题,leetcode,散列表,数据结构)