Leetcode刷题 2021.01.26

Leetcode1128 等价多米诺骨牌对的数量

给你一个由一些多米诺骨牌组成的列表 dominoes。

如果其中某一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。

形式上,dominoes[i] = [a, b] 和 dominoes[j] = [c, d] 等价的前提是 ac 且 bd,或是 ad 且 bc。

在 0 <= i < j < dominoes.length 的前提下,找出满足 dominoes[i] 和 dominoes[j] 等价的骨牌对 (i, j) 的数量。

今天的每日一题,总的来说还是比较简单的。一开始写了比较复杂的代码,还用map来存储,结果又是只击败5%。但是思路差不多是一致的,后面逐步优化,这版代码基本打败双百了。
为了知道有多少数组相同,那肯定是用map或者数组存储已经出现过的值了。小技巧就是数组hash的方式,由于值不会大于10,就用num[0] * 10 + num1,这样值就一定不会重复了。

class Solution {
    public int numEquivDominoPairs(int[][] dominoes) {
        int res = 0;
        //存储数组
        int[] map = new int[100];
        for(int i = 0; i < dominoes.length; i++){
        	//如果之前有就加多少,因为是求数组对
            int temp = hash(dominoes[i]);
            res += map[temp];
            //更新当前hash值
            map[temp]++;
        }

        return res;

    }
	
	//数组的hash,小的乘以10加大的
    private int hash(int[] num){
        if (num[0] < num[1]){
            return num[0] * 10 + num[1];
        }
        return num[1] * 10 + num[0];
    }
}

Leetcode646 最长数对链

给定一组字符,使用原地算法将其压缩。

压缩后的长度必须始终小于或等于原数组长度。

数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。

在完成原地修改输入数组后,返回数组的新长度。

这题想明白还是很容易的,因为要最长,那肯定是要让前一个数的大值尽可能小。那就是对大的值进行排序了,然后贪心的选择最小的大值进行排序就行了。话说这种给出几个数组的题基本就是排序的问题而已,

class Solution {
    public int findLongestChain(int[][] pairs) {
        int n = pairs.length;
        //对第二个数进行排序
        Arrays.sort(pairs, (x, y) ->(x[1] - y[1]));
        int prev = pairs[0][1], res = 1;

        for(int i = 1; i < n; i++){
        	//贪心的选择第一个大于前面一个数的数组,由于已经是排好序的了,所以该数组的第二个值一定也是当前最小的
            if (pairs[i][0] > prev){
                res++;
                prev = pairs[i][1];
            }
        }

        return res;

    }
}

Leetcode658 K 个最接近的元素

给定一个排序好的数组 arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。

整数 a 比整数 b 更接近 x 需要满足:

|a - x| < |b - x| 或者
|a - x| == |b - x| 且 a < b

这题给出排序好的数组,那肯定先想到二分了。先找到第一个大于等于目标值元素的下标,然后进行分析。话说这种双指针的题目有时候搞边界真是费劲啊,很想用最笨的方法一个个讨论,又觉得代码写的很难看,然后就在一次次错误中又变成了很丑的代码。希望面试的时候不要碰到这种题吧( ╯□╰ )。

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int n = arr.length;
        //二分先找到第一个大于等于目标值的下标
        int index = binarySearch(arr, x);
        List<Integer> res = new ArrayList<>();
        int j = index, i = index - 1, mid = -1;
        //mid表示数组里最接近目标值的第一个元素
        if (i < 0) {
            mid = j;
        }else{
            if (Math.abs(arr[j] - x) < Math.abs(arr[i] - x)){
                mid = j;
            }else{
                mid = i;
            }
        }
        i = mid;
        j = mid;
        //双指针进行讨论,注意边界
        while (j - i + 1 < k){
            if (i - 1 < 0){
                j++;
                continue;
            }
            if (j + 1>= n){
                i--;
                continue;
            }
            if (Math.abs(arr[j + 1] - x) < Math.abs(arr[i - 1] - x)){
                j++;
            }else{
                i--;
            }
        }
        //返回i到j之间的所有元素就行了
        for(int m = i; m <= j; m++){
            res.add(arr[m]);
        }

        return res;

    }

    private int binarySearch(int[] arr, int x){
        int i = 0, j = arr.length - 1;
        while (i < j){
            int pivot = i + (j - i) / 2;
            if (arr[pivot] < x){
                i = pivot + 1;
            }else{
                j = pivot;
            }
        }
        return i;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值