Mar5 -- Grind75

1. 3Sum -- 15

hint: If we fix one of the numbers say x, we are left with the two-sum problem at hand! For the two-sum problem, if we fix one of the numbers, say x, we have to scan the entire array to find the next number y, which is value - x where value is the input parameter. Can we change our array somehow so that this search becomes faster? 用HashMap!!

自己想- version1

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i=0; i<nums.length; i++){
            map.put(nums[i], i);
        }
        for(int i=0; i<nums.length; i++){
            int target = 0 - nums[i];
            for(int j=i+1; j<nums.length; j++){
                if(map.containsKey(target-nums[j]) && map.get(target-nums[j]) != i && map.get(target-nums[j]) != j){
                    List<Integer> res = new ArrayList<>();
                    res.add(nums[i]);
                    res.add(nums[j]);
                    res.add(target-nums[j]);
                    Collections.sort(res);
                    if(!ans.contains(res)){
                        ans.add(res);
                    }
                }
            }
        }
        return ans;
    }
}

Time Complexity: O(n^2 * m) ->the complexity of checking if the ans list already contains a list (!ans.contains(res)) is significant. For each potential triplet, this operation can take O(m) time, where m is the number of triplets already found.

但是submit的时候有Time Limit Exceeded证明有更省时的方法

自己想- version2

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        HashMap<Integer,Integer> map = new HashMap<>();
        
        for(int i=0; i<nums.length; i++){
            map.put(nums[i], i);
        }
        for(int i=0; i<nums.length; i++){
            int target = 0 - nums[i];
            for(int j=i+1; j<nums.length; j++){
                if(map.containsKey(target-nums[j]) && map.get(target-nums[j]) != i && map.get(target-nums[j]) != j){
                    List<Integer> res = new ArrayList<>();
                    res.add(nums[i]);
                    res.add(nums[j]);
                    res.add(target-nums[j]);
                    Collections.sort(res);
                    ans.add(res);
                }
            }
        }
        HashSet<List<Integer>> set = new HashSet<>();
        for(List<Integer> i: ans){
            set.add(i);
        }
        List<List<Integer>> ans1 = new ArrayList<>();
        for(List<Integer> i:set){
            ans1.add(i);
        }
        return ans1;
    }
}

于是我想多用一个hashset来解决Time Complexity的问题,但是Memory Limit Exceeded 又会增加

自己想- version3

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        HashSet<List<Integer>> ans = new HashSet<>();
        HashMap<Integer,Integer> map = new HashMap<>();
        
        for(int i=0; i<nums.length; i++){
            map.put(nums[i], i);
        }
        for(int i=0; i<nums.length; i++){
            int target = 0 - nums[i];
            for(int j=i+1; j<nums.length; j++){
                if(map.containsKey(target-nums[j]) && map.get(target-nums[j]) != i && map.get(target-nums[j]) != j){
                    List<Integer> res = new ArrayList<>();
                    res.add(nums[i]);
                    res.add(nums[j]);
                    res.add(target-nums[j]);
                    Collections.sort(res);
                    ans.add(res);
                }
            }
        }
        List<List<Integer>> set = new ArrayList<>(ans);
        return set;
    }
}

ans用hashset,这样存的时候就不会有重复的了,然后最后再把hashset转化为ListList<List<Integer>>

但是leetcode runtime很高,看看有没有别的方法

提示说可以用two pointers

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

重点:update pointers 去除掉重复的数字 ->这样就可以有distinct number 而且还不用hashset

2. Product of Array Except Self--238

Hint: For any nums[i], calculate its left product and calculate its right product, without including nums[i].
Then multiply these left and right product, This will give product of array excluding nums[i].

自己想- version1

用two pointers然后就是先往左一直乘,在往右一直乘。但是time complexity不是O(n)

Time complexity: 

Given that each inner loop's runtime depends on the position of the ith element, to calculate the total time complexity, we consider the work done across all iterations of the outer loop. For each element, the algorithm essentially iterates over all other elements in the array once (once to the left and once to the right of the current element, across all outer loop iterations).

Thus, the total work done by the algorithm is O(n^2)

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int index = 0;
        int[] res = new int[nums.length];
        for(int i=0; i<nums.length; i++){
            int ans = 1;
            int left = i-1;
            int right = i+1;
            while(left >=0){
                ans *= nums[left];
                left--;
            }
            while(right <= nums.length-1){
                ans *= nums[right];
                right++;
            }
            res[index] = ans;
            index++;
        }
        return res;
    }
}

看了Editorial的方法

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int[] ans = new int[nums.length];
        int[] left = new int[nums.length];
        int[] right = new int[nums.length];
        left[0] = 1;
        right[nums.length-1] = 1;
        for(int i=1; i<nums.length; i++){
            left[i] = left[i-1] * nums[i-1];
        }
        for(int i=nums.length-2; i>=0; i--){
            right[i] = right[i+1] * nums[i+1];
        }
        for(int i=0; i<nums.length; i++){
            ans[i] = left[i] * right[i];
        }
        return ans;
    }
}

不用extra空间

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int[] ans = new int[nums.length];
        int left = 1;
        int right = nums.length-2;
        ans[0] = 1;
        int right_product = 1;
        while(left <= nums.length-1){
            ans[left] = ans[left-1] * nums[left-1];
            left++;
        }
        while(right >= 0){
            right_product = right_product * nums[right+1];
            ans[right] = ans[right]*right_product;
            right--;
        }
        return ans;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值