字母异位词
拿一个hash[26]存字母次数,关键是利用字母的Ascill码找准字母对应的数组下标,第一个单词的字母出现一次就+1,第二个单词的字母出现一次就-1,最后检查hash[26]是不是值全为0。
package Hash;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-07-24 9:29
*/
public class ZiMuYiWeiCi {
public boolean solution(String s, String t){
int[] record = new int[26];
for (int i = 0; i < s.length(); i++){
record[s.charAt(i) - 'a']++;
}
for (int i = 0; i < t.length(); i++){
record[t.charAt(i) - 'a']--;
}
for (int now : record){
if (now != 0) return false;
}
return true;
}
public static void main(String[] args) {
String s ="abcd";
String t ="bacd";
ZiMuYiWeiCi ziMuYiWeiCi = new ZiMuYiWeiCi();
Boolean result = ziMuYiWeiCi.solution(s,t);
System.out.println("结果是:"+result);
}
}
两个数组的交集
第一步存到哈希表里(这里选用数组作为哈希表,数值就是哈希函数。选用Set作为哈希表,那set.add和set.contains。),第二步查找哈希表,第三步把重复元素加入到result这个set集合里。
package Hash;
import java.util.HashSet;
import java.util.Set;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-07-24 13:19
*/
public class ShuZuJiaoJi {
public int[] solution(int[] s, int[] t){
if (s == null || s.length == 0 || t==null || t.length == 0 )
return new int[0];
Set<Integer> set1 = new HashSet<>();
Set<Integer> resultSet = new HashSet<>();
for (int i = 0;i<s.length; i++){
set1.add(s[i]);
}
for (int i = 0;i<t.length;i++){
if (set1.contains(t[i]))
resultSet.add(t[i]);
}
return resultSet.stream().mapToInt(Integer::intValue).toArray();
}
public static void main(String[] args) {
int[] s = {4,3,5,2,1000};
int[] t = {1,2,1000,6,7,8,9};
ShuZuJiaoJi shuZuJiaoJi = new ShuZuJiaoJi();
int[] res = shuZuJiaoJi.solution(s,t);
System.out.print("数组交集是:");
for (int i:res){
System.out.print(i+",");
}
}
}
两数之和
需要查找元素是否存在,就要用哈希表,这里要存储两个数据所以用map。关键一点就是第一个问题,能想到哈希是因为要回过头查找已经遍历的元素里有没有目标值(所以其实数组暴力循环也可以,只不过是n平方的复杂度?)
package Hash;
import java.util.HashMap;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-07-25 19:35
*/
public class LiangShuZhiHe {
public int[] solution(int[] nums , int tar){
int[] res = new int[2];
if (nums == null || nums.length == 0)
return res;
HashMap<Integer, Integer> map = new HashMap<>();
for (int i =0 ; i<nums.length; i++){
int needSerach = tar -nums[i];
if (map.containsKey(needSerach)){
res[0] = i;
res[1] = map.get(needSerach);
return res;
}
map.put(nums[i],i);
}
return res;
}
public static void main(String[] args) {
int[] nums = {2,3,7,6};
LiangShuZhiHe liangShuZhiHe = new LiangShuZhiHe();
int[] res = liangShuZhiHe.solution(nums,9);
System.out.println("能加和起来等于目标值的下标是:"+res[0]+","+res[1]);
}
}
四数相加
转成两两遍历相加,把a+b的值和次数存入map里,key存值,value存次数。再两两遍历c+d的值,去找map里有没有0-(a+b)这个值!如果有就获取value即次数!把次数加起来就是四个数组之和为0的情况出现次数!代码里利用map.getOrDefault来取value值也就是出现的次数,并有个统计效果。
package Hash;
import java.util.HashMap;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-07-25 21:05
*/
public class SiShuXiangJia {
public int solution(int[] num1, int[]num2, int[]num3, int[]num4){
HashMap<Integer, Integer> map = new HashMap<>();
for (int i : num1){
for (int j : num2){
map.put(i+j, map.getOrDefault(i+j,0)+1);
}
}
int res = 0;
for (int i:num3){
for (int j: num4){
int tar = 0 - (i+j);
// res += map.get(tar);
res += map.getOrDefault(tar,0);
}
}
return res;
}
public static void main(String[] args) {
int[] num1 = {1,2};
int[] num2 = {-1,-2};
int[] num3 = {-1,2};
int[] num4 = {0,2};
SiShuXiangJia siShuXiangJia = new SiShuXiangJia();
int res = siShuXiangJia.solution(num1,num2,num3,num4);
System.out.println("加和为0的组合出现次数为:"+res);
}
}
三数之和
代码原理好懂,实行起来很多细节!a是循环主体,bc是用双指针,b在a后一位,c在数组尾部。如果三数相加等于0,把a,b,c存起来,然后b++,c–继续看。这题难在去重,a的去重就是看a等不等于a–,等于的话那目前a对应的bc,就是和a–对应的bc是一样的,就直接跳过了。另外bc的去重是存进去之后,看此时的b和b–相不相同,此时的c和c++相不相同,如果相同,要多移一次指针。主要是对a的去重要注意i>0,不然会越界。对bc的去重要注意是用while而不是if,因为可能不止有两个重复!可能有多个!所以用if
package Hash;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static java.util.Arrays.*;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-07-30 16:02
*/
public class SanShuZhiHe {
public List<List<Integer>> solution (int[] nums){
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
// int right = nums.length - 1; 不能在for循环外定义b c,因为 b和 c每一轮for循环之后就代表一个a遍历结束,新的a需要重置b c!
// int left = 1;
for (int i = 0; i<nums.length ; i++){
//最小的数都大于0,那没法组合了
if (nums[i] > 0) {
return res;
}
int right = nums.length - 1;
int left = i + 1;
//对a去重
if (i>0 && nums[i] == nums[i-1]) continue;
while (right > left){
if (nums[i] + nums[left] + nums[right] > 0 ){
right -- ;
}else if (nums[i] + nums[left] + nums[right] < 0 ){
left ++;
}else if(nums[i] + nums[left] + nums[right] == 0 ){
res.add(Arrays.asList(nums[i],nums[left],nums[right]));
//去重,不能让同样的组合计数两次 错!不能用if
// if (nums[left] == nums[left+1]) left++;
// if (nums[right] == nums[right-1]) right--;
//去重,不能让同样的组合计数多次 必须用while
while (right > left && nums[left] == nums[left+1]) left++;
while (right > left && nums[right] == nums[right-1]) right--;
left++;
right--;
}
}
}
return res ;
}
public static void main(String[] args) {
int[] nums = {-1,0,1,2,-1,-4};
SanShuZhiHe sanShuZhiHe = new SanShuZhiHe();
List<List<Integer>> res = sanShuZhiHe.solution(nums);
System.out.println(res);
}
}
四数之和
和上一题类似,多了一层循环遍历。a+b+c+d = target,思路还是双指针+遍历,双指针是c d,遍历相对上一题变成了双重循环。去重对于i , j 都要去一次!对于cd的去重则不变,同样注意是要用while多重去重而不是if!防止同样的组合被统计多次!剪枝也要剪两次,而且第二次的剪枝注意是两个之和来看!
package Hash;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-07-30 19:01
*/
public class SiShuZhiHe {
public List<List<Integer>> solution (int[] nums,int target){
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0 ; i<nums.length-1; i++){
//剪枝。 因为只有正数才能这么搞
if (nums[i]>0 && nums[i]>target) {
return res;
}
//去重
if (i>0 && nums[i] == nums[i-1]){
continue;
}
for (int j = i+1 ; j<nums.length; j++){
//剪枝! 只有正数能这么搞。
if (nums[i]+nums[j] > 0 && nums[i]+nums[j] > target){
return res;
}
//去重
if (j>i+1 && nums[j] == nums[j-1]){
continue;
}
int left = j+1;
int right = nums.length -1 ;
while (right > left){
int sum = nums[i]+nums[j]+nums[left]+nums[right];
if (sum > target){
right--;
} else if (sum < target) {
left++;
}else {
res.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
//多重去重!防止同样的组合被统计多次!
while(right > left && nums[left]==nums[left+1]) left++;
while(right > left && nums[right]==nums[right--]) right--;
left++;
right--;
}
}
}
}
return res;
}
public static void main(String[] args) {
int[] nums ={1,0,-1,0,-2,2};
int target = 0;
SiShuZhiHe siShuZhiHe = new SiShuZhiHe();
System.out.println(siShuZhiHe.solution(nums,target));
}
}