贪心2

两数之和,三数之和,最接近的三数之和(注意记录最接近的值并更新),四数之和(注意去除重复),四数之和Ⅱ(四个list,分两组,用hashmap存次数)。
整体思路:排序加双指针。

leetcode 49.字母异位词分组
new ArrayList<>()括号内参数是集合对象Collection,set,list都行。

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, ArrayList<String>> map = new HashMap<>();

        for (String str: strs) {
            char[] charArray = str.toCharArray();
            Arrays.sort(charArray);
            String strSorted = String.valueOf(charArray);
            if (map.containsKey(strSorted)) {
                map.get(strSorted).add(str);
            } else {
                map.put(strSorted, new ArrayList<String>(Arrays.asList(str)));
            }
        }
        List<List<String>> res = new ArrayList<>();
        return new ArrayList(map.values());

    }
}

leetcode149. 直线上最多的点数
注意点:

  • 长度小于3
  • 重复点
  • 记录斜率,固定一个点,这样曲线就固定了,不用考虑截距
class Solution {
    public int maxPoints(int[][] points) {
        if (points.length <= 2) {
            return points.length;
        }
        HashMap<String, Integer> map = new HashMap<>();
        int res = 0;
        for (int i = 0; i < points.length; i++) {
            int maxLine = 0;
            int numSame = 1;
            map.put("", 0);
            for (int j = i+1; j < points.length; j++) {
                String key = "";
                int numerator = points[i][1] - points[j][1];
                int denominator = points[i][0] - points[j][0];

                if (numerator == 0 && denominator == 0) {
                    numSame ++;
                } else if (numerator == 0) {
                    key = "0_1";
                } else if (denominator == 0){
                    key = "1_0";
                } else {
                    int positive = (double)numerator/denominator > 0 ? 1:-1;
                    int factor = gcd(Math.abs(numerator), Math.abs(denominator));
                  
                    numerator = Math.abs(numerator) / factor;
                    denominator = Math.abs(denominator) / factor;
                    key = String.valueOf(positive*numerator)+"_"+String.valueOf(denominator); 
                }
                if(key != "") {
                    map.put(key, map.getOrDefault(key, 0)+1);
                    if (map.get(key) > maxLine) {
                        maxLine = map.get(key);
                    }
                }
                if (maxLine + numSame > res) {
                    res = maxLine + numSame;
                }
            }
            map.clear();
        }
        return res;
    }

    public int gcd(int a, int b) {
        if (a == 0)
            return b;
        if (a > b) {
            return gcd(b, a);
        } else {
            return gcd(b%a, a);
        }
    }
}

leetcode219. 存在重复元素Ⅱ
散列表,或者一个先进先出的队列
leetcode220. 存在重复元素Ⅲ
桶,[0, t], [t+1, 2t+1],...只要找到有没有在同一个桶的,或者相邻桶内,差别大小在范围内的,有没有可能说一个桶内有两个元素呢?不可能,有相同元素就直接返回了。
所以桶内的元素一定是最新的窗口内的元素。
或者使用TreeSet,和Set区别在于,Set是散列表,而TreeSet是有序的,可以方便地查找前后元素。

class Solution {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        TreeSet<Long> tset = new TreeSet<>();
        for (int i=0;i<nums.length;i++) {
            Long s = tset.ceiling((long) nums[i]);
            if (s!=null && s-nums[i] <= t)
                return true;

            s = tset.floor((long) nums[i]);
            if (s!=null && nums[i] - s <= t)
                return true;
            tset.add((long) nums[i]);
            if (i>=k)
                tset.remove((long) nums[i-k]);
        }
        return false;
    }
}

leetcode447.回旋镖的数量
每个点都不一样,枚举+哈希

class Solution {
    public int numberOfBoomerangs(int[][] points) {

        int res = 0;

        //O(n^2)
        for(int i = 0; i < points.length;i++){
            Map<Integer, Integer> record = new HashMap<>();
            for(int j = 0; j < points.length; j ++){
                if( j != i )
                    if(record.containsKey(distance(points[i], points[j]))){
                        record.put(distance(points[i], points[j]),
                                record.get(distance(points[i], points[j])) + 1);
                    }
                    else
                        record.put(distance(points[i], points[j]), 1);
            }
            for(int k : record.values()){
                if(k >= 2)//这里其实可以不加这句,因为k=1或k=0,结果都是0,但是加上可以减少一定的计算量。
                    res += k * (k - 1);
            }
            
        }

        return res;
    }

    private int distance(int[] x, int[] y){

        return (x[0] - y[0]) * (x[0] - y[0]) + (x[1] - y[1]) * (x[1] - y[1]);
    }
}

posted @ 2020-08-28 22:49  我的小叮当  阅读(155)  评论(0编辑  收藏  举报