454.四数相加
关键词:降低时间复杂度,使用map存放值和个数
暴力解法就是四个for循环去遍历,为了达到更优的时间复杂度,就去两两遍历查找,复杂度为O(n²)
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
HashMap<Integer, Integer> map = new HashMap<>();
int result = 0;
//⏰只用到数组的值就可以使用foreach遍历,map获取没有则使用getOrDefault给出默认值
for (int i : nums1) {
for (int j : nums2) {
int sum = i + j;
map.put(sum, map.getOrDefault(sum,0)+1);
}
}
// for(int i = 0; i <nums1.length; i++){
// for(int j = 0; j <nums2.length; j++){
// int count = nums1[i] + nums2[j];
// if(map.containsKey(count)){
// map.put(count, map.get(count)+1);
// }else{
// map.put(count, 1);
// }
// }
// }
for (int i : nums3) {
for (int j : nums4) {
int sum = 0 - (i + j);
result += map.getOrDefault(sum, 0);
}
}
// for(int i = 0; i <nums3.length; i++){
// for(int j = 0; j <nums4.length; j++){
// int count = 0 - (nums3[i] + nums4[j]);
// if(map.containsKey(count)){
// result += map.get(count);
// }
// }
// }
return result;
}
}
383.赎金信
关键词:str1中是否包含str2
本题和有效字母异位词的区别是:有效字母异位数个数是一致的,所以只要判断最后的哈希数组有值!=0,则为false;但这里面个数是不一致的,所以就要magazine++,ransomNote--,此时有负数则说明ransomNote中有的字符在magazine中没有
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] arr = new int[26];
if(ransomNote.length() > magazine.length()){
return false;
}
for(int i=0; i<magazine.length(); i++){
int index = magazine.charAt(i) - 'a';
arr[index]++;
}
for(int i=0; i<ransomNote.length(); i++){
int index = ransomNote.charAt(i) - 'a';
arr[index]--;
}
for(int i : arr){
if(i<0) return false;
}
return true;
}
}
15.三数之和
关键词:ijk不相等;总和为0;元素不重复
双指针法、校验重复元素,先存放本次情况,下次再遇到就跳过
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//使用双指针法
List<List<Integer>> result = new ArrayList<>();
//先对数组排序
Arrays.sort(nums);
//定义遍历数组的i、left、right
for(int i = 0; i<nums.length; i++){
if(nums[i]>0){
return result;
}
//对a去重
if(i>0&&nums[i]==nums[i-1]){
continue;
}
int left = i + 1;
int right = nums.length - 1;
while(right > left){
int sum = nums[i] + nums[left] +nums[right];
if(sum > 0){
right--;
}else if(sum < 0){
left++;
}else{
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
//对b、c去重
while(left<right && nums[right]== nums[right-1]) right--;
while(left<right && nums[left]== nums[left+1]) left++;
left++;
right--;
}
}
}
return result;
}
}
18.四数之和
关键词:abcd各个下标值不相同,四元组元素不重复
剪枝+去重:相较于三数之和多了一层循环,以及此处的target可能为负数,简直操作中限制条件要>=0
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
//相较于三数之和多了一层循环
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for(int k = 0; k<nums.length; k++){
//剪枝
if(nums[k]>=0 && nums[k]>target){
break;
}
//去重
if(k>0 && nums[k] == nums[k-1]){
continue;
}
for(int i = k+1; i<nums.length; i++){
//剪枝 将k和i作为一个整体
if(nums[k]+nums[i]>=0 && nums[k]+nums[i]>target){
break;
//⏰return result;这种写法在此处不正确!只是跳出当前这层循环!不是所有循环!
}
//去重
if(i>k+1 && nums[i] == nums[i-1]){
continue;
}
int left = i+1;
int right = nums.length-1;
while(left < right){
int sum = nums[k]+nums[i]+nums[left]+nums[right];
if(sum > target){
right--;
}else if(sum < target){
left++;
}else{
result.add(Arrays.asList(nums[k], nums[i], nums[left], nums[right]));
while(left<right && nums[right]==nums[right-1]) right--;
while(left<right && nums[left]==nums[left+1]) left++;
right--;
left++;
}
}
}
}
return result;
}
}