Leetcode刷题 2021.03.13
Leetcode447 回旋镖的数量
给定平面上 n 对 互不相同 的点 points ,其中 points[i] = [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 ,其中 i 和 j 之间的距离和 i 和 k 之间的距离相等(需要考虑元组的顺序)。
返回平面上所有回旋镖的数量。
印象里好像做过这题了,今天又发现没有提交过,(lll¬ω¬)。题目还是比较基础的,数量小于500,一定就是O(n^2)的解法了。要求距离相等,那一定是记录之前算过的距离了,考虑用hashmap实现。
class Solution {
public int numberOfBoomerangs(int[][] points) {
if (points.length < 3) return 0;
int n = points.length, res = 0;
for(int i = 0; i < n; i++){
Map<Integer, Integer> map = new HashMap<>();
for(int j = 0;j < n; j++){
if (i == j) continue;
//记录一下算过的距离,如果有相等的距离就加一
int distance = (points[i][0] - points[j][0]) * (points[i][0] - points[j][0]) + (points[i][1] - points[j][1]) * (points[i][1] - points[j][1]);
// System.out.println(distance);
map.put(distance, map.getOrDefault(distance, 0) + 1);
}
//这里等于val * (val - 1),具体用个例子想想就知道了
for(int val : map.values()){
res += val * (val - 1);
}
}
return res;
}
}
Leetcode705 设计哈希集合
不使用任何内建的哈希表库设计一个哈希集合(HashSet)。
实现 MyHashSet 类:
void add(key) 向哈希集合中插入值 key 。
bool contains(key) 返回哈希集合中是否存在这个值 key 。
void remove(key) 将给定值 key 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。
感觉这种设计的题也是蛮多见的,考的最多的应该就是LRU了,然后设计一个hashmap,或者阻塞队列等等。好像看到了14号的每日一题和这个差不多,明天在记录吧。
class Solution {
List<List<Integer>> edge = new ArrayList<>();
public int[] loudAndRich(int[][] richer, int[] quiet) {
int n = quiet.length;
for(int i = 0; i < n; i++){
edge.add(new ArrayList<>());
}
//先构建边
for(int[] rich : richer){
edge.get(rich[1]).add(rich[0]);
}
//构建数组,并且初始化为-1
int[] res = new int[n];
Arrays.fill(res, -1);
for(int i = 0; i < n; i++){
//从底向上递归
helper(res, quiet, i);
}
return res;
}
private int[] helper(int[] res, int[] quiet, int index){
//如果已经有结果了,就返回当前的下标和安静值
if (res[index] != -1) return new int[]{res[index], quiet[res[index]]};
//如果一个点没有比它更富有的人,那就更新它的结果,并返回它的下标和安静值
if (edge.get(index).size() == 0){
res[index] = index;
return new int[]{index, quiet[index]};
}
//否则就进行递归,不断更新结果
int min = quiet[index];
res[index] = index;
for(int i = 0; i < edge.get(index).size(); i++){
int[] temp = helper(res, quiet, edge.get(index).get(i));
if (temp[1] < min){
min = temp[1];
res[index] = temp[0];
}
}
//最后返回自己的结果就行了
return new int[]{res[index], min};
}
}
Leetcode556 下一个更大元素 III
给你一个正整数 n ,请你找出符合条件的最小整数,其由重新排列 n 中存在的每位数字组成,并且其值大于 n 。如果不存在这样的正整数,则返回 -1 。
注意 ,返回的整数应当是一个 32 位整数 ,如果存在满足题意的答案,但不是 32 位整数 ,同样返回 -1 。
这题和31题是一模一样的题,也是字节比较喜欢考的题目吧。想法就是贪心的从后往前选一个比之前大的数,然后交换它们的位置,反转一下顺序就行了。
class Solution {
public int nextGreaterElement(int n) {
char[] arr = String.valueOf(n).toCharArray();
int i = arr.length - 2;
//从后往前找一个大于前一个元素的数
while (i >= 0 && arr[i] >= arr[i + 1]){
i--;
}
//如果没有,就说明找不到更大的了
if (i == -1) return -1;
int j = arr.length - 1;
//从后往前找第一个大于索引位置的数
for(; j > i; j--){
if (arr[j] > arr[i]){
break;
}
}
//交换两个数
swap(arr, i, j);
//交换之后i位置之后一定是降序排列了,把他们反转成升序排列
reverse(arr, i + 1, arr.length - 1);
long sum = 0;
for(int k = 0; k < arr.length; k++){
sum = sum * 10 + arr[k] - '0';
}
if (sum > Integer.MAX_VALUE) return -1;
return (int)sum;
}
private void swap(char[] nums, int i, int j){
char temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
private void reverse(char[] nums, int i, int j){
while (i < j){
swap(nums, i, j);
i++;
j--;
}
}
}