两数之和,三数之和,最接近的三数之和(注意记录最接近的值并更新),四数之和(注意去除重复),四数之和Ⅱ(四个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]);
}
}