LeetCode算法练习top100:(1)哈希、双指针、滑动窗口

package jz.top100;

import java.util.*;

public class Top100 {
    //1. 两数之和
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++) {
            if(map.get(target - nums[i]) != null) {
                return new int[]{i, map.get(target - nums[i])};
            } else {
                map.put(nums[i], i);
            }
        }
        return null;
    }

    //49. 字母异位词分组
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String, ArrayList<String>> map = new HashMap<>();
        for (String s : strs) {
            char[] chars = s.toCharArray();
            Arrays.sort(chars);
            String s0 = Arrays.toString(chars);
            if (map.containsKey(s0)) {
                map.get(s0).add(s);
            } else {
                ArrayList<String> list = new ArrayList<>();
                list.add(s);
                map.put(s0, list);
            }
        }
        return new ArrayList<List<String>>(map.values());
    }

    //128. 最长连续序列
    //方法1:排序
    public int longestConsecutive(int[] nums) {
        //数字连续,从任意一个数组出发,遍历最长连续数组
        if (nums.length == 0) {
            return 0;
        }
        int cur = 1, max = 1;
        Arrays.sort(nums);
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == nums[i - 1] + 1) { //连续
                cur++;
                max = Math.max(max, cur);
            } else if (nums[i] == nums[i - 1]){ //相等则忽略
                continue;
            } else { //不连续,重新开始
                cur = 1;
            }
        }
        return max;
    }
    //方法2:hashset
    public int longestConsecutive(int[] nums) {
        //hashset记忆
        HashSet<Integer> set = new HashSet<>();
        for (int num : nums) {
            set.add(num);
        }
        int res = 0;
        for (int num : set) { //只需遍历去重后的数字
            int cur = num;
            //判断当前节点是不是连续序列的起点,不连续才是起点
            if (!set.contains(cur - 1)) {
                while (set.contains(cur + 1)) {
                    cur++;
                }
            }
            res = Math.max(res, cur - num + 1);
        }
        return res;
    }

    //283. 移动零
    public void moveZeroes(int[] nums) {
        int n = nums.length;
        //把不是0的元素放到前面,剩下的元素置0
        int index = 0;
        for (int i = 0; i < n; i++) {
            if (nums[i] != 0) {
                nums[index] = nums[i];
                index++;
            }
        }
        for (int i = index; i < n; i++) {
            nums[i] = 0;
        }
    }

    //11. 盛最多水的容器
    public int maxArea(int[] height) {
        if (height.length < 2) {
            return 0;
        }
        int max = 0;
        int i = 0, j = height.length - 1;
        while (i < j) {
            max = Math.max(max, (j - i) * Math.min(height[i], height[j]));
            if (height[i] < height[j]) { //向内移动短板
                i++;
            } else {
                j--;
            }
        }
        return max;
    }

    //15. 三数之和
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums.length < 3) {
            return res;
        }
        Arrays.sort(nums);
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], i);
        }
        int a, b, c;
        for (int i = 0; i < nums.length - 2; i = map.get(a) + 1) {
            a = nums[i];
            for (int j = i + 1; j < nums.length - 1; j = map.get(b) + 1) {
                b = nums[j];
                c = -a - b;
                if (c < b) {
                    break;
                }
                if (map.containsKey(c) && map.get(c) > j) {
                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(a);
                    list.add(b);
                    list.add(c);
                    res.add(list);
                }
            }
        }
        return res;
    }

    //42. 接雨水
    public int trap(int[] height) {
        int res = 0;
        for (int i = 1; i < height.length - 1; i++) {
            //寻找左边最高的墙
            int maxLeft = 0;
            for (int j = i - 1; j >= 0; j--) {
                if (height[j] > maxLeft) maxLeft = height[j];
            }
            //寻找右边最高的墙
            int maxRight = 0;
            for (int j = i + 1; j < height.length; j++) {
                if (height[j] > maxRight) maxRight = height[j];
            }
            //可以存储水的高度取决于较矮的抢
            int min = Math.min(maxLeft, maxRight);
            if (min > height[i]) {
                res += min - height[i];
            }
        }
        return res;
    }

    //3. 无重复字符的最长子串
    public int lengthOfLongestSubstring(String s) {
        if (s.length() == 0) return 0;
        int left = 0, right = 0, res = 0;
        HashMap<Character, Integer> map = new HashMap<>();
        while (right < s.length()) {
            char c = s.charAt(right);
            if (map.containsKey(c)) {
                left = Math.max(left, map.get(c) + 1); //使得字串无重复
            }
            map.put(c, right);
            res = Math.max(res, right - left + 1);
            right++;
        }
        return res;
    }

    //438. 找到字符串中所有字母异位词
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        if (s.length() < p.length()) {
            return res;
        }
        //统计滑动窗口内各个字符出现的次数,次数相同,则是异位词
        int[] scnt = new int[26];
        int[] pcnt = new int[26];
        //初始窗口
        for (int i = 0; i < p.length(); i++) {
            scnt[s.charAt(i) - 'a']++;
            pcnt[p.charAt(i) - 'a']++;
        }
        if (Arrays.equals(scnt, pcnt)) { //判断数组是否相同:Arrays.equals
            res.add(0);
        }
        for (int i = p.length(); i < s.length(); i++) {
            //移动窗口,先减去左边界,右边界加1
            scnt[s.charAt(i - p.length()) - 'a']--;
            scnt[s.charAt(i) - 'a']++;
            if (Arrays.equals(scnt, pcnt)) {
                res.add(i - p.length() + 1);
            }
        }
        return res;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值