Leetcode百题斩-哈希

看来面试前还是要老老实实刷leetcode为好,今天看到一个题库,leetcode百题斩,刚好最近面试的这两题全在里面。瞄了一眼,也有不少题之前居然也刷过。那么,冲冲冲,看多久能把这百题刷完。

第一天,先刷第一个专题哈希。感觉作为一个竞赛生,刷这种题应该没什么难度。那就不用C++了,直接上JAVA

1. Two Sum[Easy]

思路:作为leetcode首题,太经典的哈希表了

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> numMap = new HashMap<>();
        int len = nums.length;
        for (int i = 0; i < len; i++) {
            int complement = target - nums[i];
            if (numMap.containsKey(complement)) {
                return new int[] {numMap.get(complement), i};
            }
            numMap.put(nums[i], i);
        }
        return null;
    }
}

49. Group Anagrams[Mediam]

思路:异位字母分组,直接将字母排序后进行哈希

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> groupMap = new HashMap<>();
        for (String str : strs) {
            String sortedStr = sortString(str);
            groupMap.computeIfAbsent(sortedStr, k -> new ArrayList<>()).add(str);
        }
        return new ArrayList<>(groupMap.values());
    }

    private String sortString(String s) {
        char[] stringC = s.toCharArray();
        Arrays.sort(stringC);
        return new String(stringC);
    }
}

128. Longest Consecutive Sequence[Medium]

思路:最长连续序列,第一想法就是直接排序,然后进行统计。复杂度为 O(nlogn)。注意特判一下空数组即可

class Solution {
    public int longestConsecutive(int[] nums) {
         if (nums == null || nums.length == 0) {
            return 0;
        }
        Arrays.sort(nums);
        int numLen = nums.length;
        int curLen = 1;
        int maxLen = 1;
        for (int i = 0; i < numLen; i++) {
            if (i > 0 && nums[i] == nums[i - 1] + 1) {
                curLen++;
                if (curLen > maxLen) {
                    maxLen = curLen;
                }
            } else if (i == 0 || nums[i] != nums[i - 1]) {
                curLen = 1;
            }
        }
        return maxLen;
    }
}

既然这题被分在了哈希专栏里,那么想想是否可以通过哈希的方法将复杂度降到 O(n)。那么排序肯定是排不了了,直接将数组维护在哈希集合中,遍历集合元素,针对每段连续序列的头节点(该数的前一个数不在集合中),向后判断该段连续序列长度

class Solution {
    public int longestConsecutive(int[] nums) {
         if (nums == null || nums.length == 0) {
            return 0;
        }
        HashSet<Integer> numSet = new HashSet<>();
        int maxLen = 1;
        for (int num : nums) {
            numSet.add(num);
        }
        for (int num : numSet) {
            if (!numSet.contains(num - 1)) {
                int curlen = 1;
                while (numSet.contains(num + curlen)) {
                    curlen++;
                }
                if (curlen > maxLen) {
                    maxLen = curlen;
                }
            }
        }
        return maxLen;
    }
}

不过虽然这个算法将复杂度降下来了,但是最终的耗时其实还不如排序,可见现在的排序优化已经十分到位了。

560. Subarray Sum Equals K[medium]

思路:求数串中和为k的子串。想到子串问题,当然就想到了前缀和。两个前缀和的差值即为一个子串和。因此,哈希表维护一下前缀和及对应数量。由于 sum(current)-sum(need)=k,因此只需要遍历前缀和,寻找哈希表中 sum-k 对应的数量即可

class Solution {
    public int subarraySum(int[] nums, int k) {
       Map<Integer, Integer> sumMap = new HashMap<>();
        int count = 0;
        int sum = 0;
        sumMap.put(0, 1);
        for (int num : nums) {
            sum += num;
            int need = sum - k;
            if (sumMap.containsKey(need)) {
                count += sumMap.get(need);
            }
            sumMap.put(sum, sumMap.getOrDefault(sum, 0) + 1);
        }
        return count;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值