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;
}
}