思路见注释。主要是太累了,他奶奶的去工地干了半天,回来写算法,对比之下,我发现那么热,那么累都抗的下来,这点算法算什么,吃不了学习的苦就得吃生活的苦,现在的我或许更喜欢吃学习的苦吧!
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
//定义map集合,分别存储两个数组的和key次数value
Map<Integer,Integer> hash=new HashMap<>();
//定义count,存书最终的元祖数量
int count=0;
for(int a:nums1){
for(int b:nums2){
//getOrDefauat函数的意思是,如果存在key则返回key
//对应的value,不存在,返回默认值
hash.put(a+b,hash.getOrDefault(a+b,0)+1);
}
}
//map集合中存储的是两个数组组合之后对应的和以及次数
for(int a:nums3){
for(int b:nums4){
if(hash.containsKey(0-(a+b))){
count+=hash.get(0-(a+b));
}
}
}
return count;
}
}
思路:就是使用hash表进行判断,跟昨天字母异或差不多,这里使用数组是为了节省内存
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int rlen=ransomNote.length();
int mlen=magazine.length();
if(rlen>mlen){
return false;
}
int[] hash=new int[26];
//便利字符串,将字母作为键,次数作为值
for(int i=0;i<rlen;i++){
hash[ransomNote.charAt(i)-'a']++;
}
for(int j=0;j<mlen;j++){
hash[magazine.charAt(j)-'a']--;
}
for(int x:hash){
if(x>0){
return false;
}
}
return true;
}
}
双指针的思路,将算法的时间复杂度将第一个阶,排序感觉是这个算法解决本道题的精髓
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int len=nums.length;
if(len<3){
return null;
}
List<List<Integer>> result=new ArrayList<>();
int left;
int right;
//首先对数组进行排序
Arrays.sort(nums);
//定义双指针left,right指向数组的左右,如果a+b>c
//rght右移,同理移
for(int i=0;i<len;i++){
if(nums[i]>0){
return result;
}
left=i+1;
right=len-1;
if(i>0&&nums[i]==nums[i-1]){
continue;//说明的值重复了就不可以在使用,跳过。
}
while(left<right){//如果left==right说明此时只有元素
int sum=nums[i]+nums[left]+nums[right];
if(sum>0){
right--;
}else if(sum<0){
left++;
}else{//找到一个结果
// temp.add(nums[i]);
// temp.add(nums[left]);
// temp.add(nums[right]);
result.add(Arrays.asList(
nums[i],nums[left],nums[right]));
//对left和right进行去重
while(left<right&&
nums[right]==nums[right-1]){
right--;
}
while(left<right&&
nums[left]==nums[left+1]){
left++;
}
left++;
right--;
}
}
}
return result;
}
}
三树之和ProMax,昨晚三树之和其实这个Sioux也很好理解
注*:什么是剪枝操作?
一种算法优化,通过某种判断,避免不必要的索引遍历
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result=new ArrayList<>();
int len=nums.length;
if(len<4){
//进行第一次剪枝操作
return result;
}
//对数组进行排序
Arrays.sort(nums);
for(int i=0;i<len;i++){
//进行第二次剪枝
if(nums[i]>target&&nums[i]>0){
break;
}
//对i进行去重操作,当前nums[i]已经被使用过,所以下一次直接跳过
if(i>0&&nums[i]==nums[i-1]){
continue;
}
//进入第二层循环
for(int k=i+1;k<len;k++){
//进行第三次剪枝
if(nums[i]+nums[k]>target&&target>=0){
break;
}
//对k进行去重操作
if(k>i+1&&nums[k]==nums[k-1]){
continue;
}
//使用双指针进行判断
int left=k+1;
int right=len-1;
while(left<right){
int sum=nums[i]+nums[k]+nums[left]+nums[right];
if(sum>target){
right--;
}else if(sum<target){
left++;
}else{
result.add(Arrays.asList(nums[i],nums[k],nums[left],nums[right]));
//添加元素之后需要立即对left和right进行去重操作
//注意,如果重复指针就会移动,这时候之前的循环判断条件left<right可能就不成立
//所以仍然需要进行判断,这不是多余操作
while(left<right&&nums[left]==nums[left+1]){
left++;
}
while(left<right&&nums[right]==nums[right-1]){
right--;
}
//去重结束之后,指针移动搜索下一个目标
left++;
right--;
}
}
}
}
return result;
}
}
Create The Code Change The World!!
---三条直线围墙