代码随想录第六天|四数相加II |赎金信 |三数之和|四数之和

四数相加II

该题与两数之和类似,由于结果只要返回符合条件的元组数,所以可以将四个数组看成两个大组,用一个map来记录两个大组中两个数组所有元素的可能的和以及出现的次数,然后再通过两个for循环来遍历另外一个大组中的两个数组元素,与map中记录的和进行相加,若相加等于target值,则返回map中记录的次数。

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        HashMap<Integer,Integer> map=new HashMap<>();
        int sumcount=0;
        for(int i=0;i<nums1.length;i++){
            for(int j=0;j<nums2.length;j++){
                int sum=0;
                sum=nums1[i]+nums2[j];
                int count=0; 
                if(map.containsKey(sum)){
                    int value;
                    value=map.get(sum);
                    value++;
                    map.put(sum,value);
                }else{
                    count++;
                    map.put(sum,count);
                }    
            }
        }
        for(int p=0;p<nums3.length;p++){
            int sum1=0;
            for(int q=0;q<nums4.length;q++){
                sum1=nums3[p]+nums4[q];
                if(map.containsKey(0-(sum1))){
                    sumcount+=map.get(0-(sum1));
                }
            }
        }
        return sumcount;
    }
}

赎金信

该题与有效字母异位词类似,都是小写字母,元素大小有限,可以通过下标映射使用hash数组。这里使用哈希数组映射ransomNote中的字母,与magazine字符串进行判断,若ransomNote中的字母在magazine字符串中出现过,则将该位置减1.最后若哈希数组中所有元素为0,则符合条件。

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] arr=new int[26];
        for(int i=0;i<ransomNote.length();i++){ //先将ransomnote字符串映射到数组中
            arr[ransomNote.charAt(i)-'a']++;
        }
        for(int j=0;j<magazine.length();j++){  //遍历magazine字符串,看其是否包含
            if(arr[magazine.charAt(j)-'a']!=0){ //ransomnote字符串
                arr[magazine.charAt(j)-'a']--;
            }
        }
        for(int p=0;p<arr.length;p++){
            if(arr[p]!=0){
                return false;
            }
        }
        return true;

    }
}

三数之和

这里三数之和有去重的要求,使用哈希法会比较麻烦,这里又是使用双指针的解法。首先将数组进行排序,以数组A为例。A[i]为起点,A[i+1]为左指针起点,A[size-1]为右指针起点位置。通过A[i]+A[left]+A[right]与target进行比较,若小了,则将左指针右移,若大了,则将右指针向左移。直到找到符合条件的左右指针。然后再接着移动i进行新的一轮查找。这里剪枝和去重操作见代码随想录讲解

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result=new ArrayList<>();
        List<Integer> res=new ArrayList<>();
        quicksort(nums,0,nums.length-1);
        if(nums[0]>0){
                return result;
            }
        for(int i=0;i<nums.length-1;i++){
            if(i>0&&nums[i]==nums[i-1]){
                continue;
            }
            int left=i+1;
            int right=nums.length-1;
            while(left<right){
                int sum=nums[i]+nums[left]+nums[right];
                if(sum<0){
                    left++;
                }else if(sum>0){
                    right--;
                }else{
                    result.add(Arrays.asList(nums[i],nums[left],nums[right]));
                    while(left<right&&nums[left]==nums[left+1]){
                        left++;
                    }
                    left++;
                    while(left<right&&nums[right]==nums[right-1]){
                        right--;
                    }
                    right--;
                }
              
            }
              
        }
        return result;

    }
    public void quicksort(int[] nums,int start,int end){
        if(start>=end){
            return ;
        }
        int p=parition(nums,start,end);
        quicksort(nums,start,p-1);
        quicksort(nums,p+1,end);

    }
    public int parition(int[] nums,int start,int end){
        int left=start;
        int right=end;
        int privot=nums[start];
        int temp;
        while(left!=right){
            while((nums[right]>privot)&&(left<right)){
                right--;
            }
            while((nums[left]<=privot)&&(left<right)){
                left++;
            }
            if(left<right){
              temp=nums[left];
              nums[left]=nums[right];
              nums[right]=temp;  
            }
        }
        nums[start]=nums[left];
        nums[left]=privot;
        return left;
    }
}

四数之和

这题与三数之和类似,多加入一个for循环,但是里面的剪枝操作有些区别,二级循环中的剪枝操作只能是退出当前循环。

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){  //剪枝操作
                return result;
            }
            if(k>0&&nums[k]==nums[k-1]){  //去重操作
                continue;
            }

            for(int i=k+1;i<nums.length;i++){
                if(target>0&&nums[k]+nums[i]>target){  //剪枝操作
                    break;                              //这里只是退出当前二级循环
                }
                if(i>k+1&&nums[i]==nums[i-1]){     //去重操作
                    continue;
                }
                int l=i+1;
                int r=nums.length-1;
                while(l<r){
                    int sum=nums[k]+nums[i]+nums[l]+nums[r];
                    if(sum<target){
                        l++;
                    }else if(sum>target){
                        r--;
                    }else{
                        result.add(Arrays.asList(nums[k],nums[i],nums[l]
                        ,nums[r]));
                        while(l<r&&nums[r]==nums[r-1]){
                            r--;
                        }
                        r--;
                        while(l<r&&nums[l]==nums[l+1]){
                            l++;
                        }
                        l++;
                    }
                }
            }

        }
        return result;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值