Leetcode punch

2020/4/18

Array topic medium difficulty

1

238. The product of arrays other than themselves

Gives you an integer array nums of length n, where n> 1, returns the output array output, where output [i] is equal to the product of nums except nums [i].

Example:

Input: [1,2,3,4]
Output: [24,12,8,6]

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

2

56. Merging interval

Given a set of intervals, please merge all overlapping intervals.

Example 1:

Input: [[1,3], [2,6], [8,10], [15,18]]
Output: [[1,6], [8,10], [15,18]]
Explanation: The interval [1,3] and [2,6] overlap, and merge them into [1,6].
Example 2:

Input: [[1,4], [4,5]]
Output: [[1,5]]
Explanation: The intervals [1,4] and [4,5] can be regarded as overlapping intervals.

Idea: The array is arranged in ascending order of the first seat, descending order of the second seat, and then looped. If the current right short point is less than the left short point of the loop time, it is divided once, and then the loop node continues as the current node Cycle on.

class Solution {
    public int[][] merge(int[][] intervals) {
        if(intervals.length<2)
        return intervals;
        Arrays.sort(intervals,(o1,o2)->{
            return o1[0]==o2[0]?o2[1]-o1[1]:o1[0]-o2[0];
        });
        List<Integer> list = new ArrayList<>();
        int left =intervals[0][0];
        int right = intervals[0][1];
        for(int i=1;i<intervals.length;i++){
            if(right>=intervals[i][0]){
                right=Math.max(right,intervals[i][1]);
            }else{
                list.add(left);
                list.add(right);
                left=intervals[i][0];
                right=intervals[i][1];
            }
        }
               list.add(left);
                list.add(right);
        int[][] ans = new int[list.size()/2][2];
        for(int i=0;i<list.size()/2;i++){
            ans[i][0]=list.get(i*2);
            ans[i][1]=list.get(i*2+1);
        }
        return ans;
    }
}

3

287. Looking for duplicates

Given an array nums containing n + 1 integers, the number of which is between 1 and n (including 1 and n), it can be seen that there is at least one repeated integer. Assuming there is only one repeated integer, find the repeated number.

Example 1:

Input: [1,3,4,2,2]
Output: 2
Example 2:

Input: [3,1,3,4,2]
Output: 3

class Solution {
    public int findDuplicate(int[] nums) {
        int[] arr= new int[nums.length];
        for(int i=0;i<nums.length;i++){
        arr[nums[i]]++;
        if(arr[nums[i]]>1)
        return nums[i];
        }
        return 0;
        
    }
}

4

442. Duplicate data in the array

Given an integer array a, where 1 ≤ a [i] ≤ n (n is the length of the array), some of the elements appear twice and others appear once.

Find all elements that appear twice.

Can you solve this problem in O (n) time complexity without using any extra space?

Examples:

Input:
[4,3,2,7,8,2,3,1]

Output:
[2,3]

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        int[] arr = new int[nums.length+1];
        List<Integer> ans = new ArrayList<>();
        for(int i=0;i<nums.length;i++){
            arr[nums[i]]++;
            if(arr[nums[i]]>1)
            ans.add(nums[i]);
        }
        return ans;
    }
}

5

289. Game of Life

According to Baidu Encyclopedia, the game of life, referred to as life for short, is a cellular automaton invented by British mathematician John Horton Conway in 1970.

Given a panel containing m × n grids, each grid can be regarded as a cell. Each cell has an initial state: 1 is a live cell (live), or 0 is a dead cell (dead). Each cell and its eight adjacent locations (horizontal, vertical, diagonal) follow the following four laws of survival:

If the number of viable cells in the eight locations around the viable cell is less than two, the viable cell in that location is dead;
if there are two or three viable cells in the eight locations around the viable cell, the viable cell in that location is still alive;
if the viable cell If there are more than three living cells in the eight surrounding locations, the living cells at that location will die;
if there are exactly three living cells around the dead cells, the dead cells at that location will be resurrected;
according to the current state, write a function to calculate the total number of cells on the panel. A state (after an update). The next state is formed by applying the above rules to each cell in the current state at the same time, where the birth and death of the cells occur simultaneously.

Examples:

Input:
[
[0,1,0],
[0,0,1],
[1,1,1],
[0,0,0]
]
Output:
[
[0,0,0],
[1,0 , 1],
[0,1,1],
[0,1,0]
]

class Solution {
    private int[] dx = {-1,-1,-1,0,1,1,1,0};
    private int[] dy = {-1,0,1,1,1,0,-1,-1};

    public void gameOfLife(int[][] board) {
       int m = board.length;
        if(m==0)
        return;
       int n = board[0].length;
        if(n==0)
        return;
        int[][] ans = new int[m][n];
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                game(i,j,board[i][j],board,ans,m,n);
            }
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                board[i][j]=ans[i][j];
            }
        }
    }

    private void game(int i,int j,int state,int[][] board,int[][] ans,int m,int n){
        int cnt1=0;
        int cnt2=0;
        for(int k=0;k<8;k++){
            int x=i+dx[k];
            int y=j+dy[k];
            if(x>=0&&x<m&&y>=0&&y<n){
                if(board[x][y]==0){
                    cnt1++;//死亡细胞数
                }else{
                    cnt2++;//活细胞数
                }
               
            }
        }
        if(state==1&&cnt2==2){
        ans[i][j]=1;
        }
        if(state==1&&cnt2==3){
        ans[i][j]=1;
        }
        if(state==0&&cnt2==3)
        ans[i][j]=1;

    }

}

6

77. Combination

Given two integers n and k, return all possible combinations of k in 1 ... n.

Example:

Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

class Solution {
    List<List<Integer>> lists = new ArrayList<>();
    public List<List<Integer>> combine(int n, int k) {
        if(n<k)
        return lists;
        List<Integer> list = new ArrayList<>();
        dfs(n,k,1,list);
        return lists;
    }

    public void dfs(int n,int k,int start,List<Integer> list){
        if(list.size()==k){
            lists.add(new ArrayList<>(list));
            return;
        }
        for(int i=start;i<=n;i++){
            list.add(i);
            dfs(n,k,i+1,list);
            list.remove(list.size()-1);
        }
    }
}

7

39. Combined sum

Given an array of duplicates with no duplicate elements and a target number target, find out all the combinations that can make the sum of the numbers in the targets.

The numbers in candidates can be selected repeatedly without restriction.

Description:

All numbers (including target) are positive integers.
The solution set cannot contain duplicate combinations.
Example 1:

Input: candidates = [2,3,6,7], target = 7,
the solved set is:
[
[7],
[2,2,3]
]
Example 2:

Input: candidates = [2,3,5], target = 8,
the solved set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]

class Solution {

    private List<List<Integer>> lists = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        if(candidates==null||candidates.length==0||target<0)
        return lists;
        List<Integer> list = new ArrayList<>();
        dfs(candidates,0,target,list);
        return lists;
    }

    public void dfs(int[] candidates,int start,int target,List<Integer> list){
        if(target<0){
        return;
        }

        if(target==0){
            lists.add(new ArrayList<>(list));
        }
        for(int i=start;i<candidates.length;i++){
            list.add(candidates[i]);
            dfs(candidates,i,target-candidates[i],list);
            list.remove(list.size()-1);
        }
    }
}

The algorithm structure given by the title is

class Solution {
public List<List> combinationSum(int[] candidates, int target) {

}

}
First of all, the title requires that the returned type is List <List>, then we create a new List <List> as a global variable, and finally return it.

class Solution {
List<List> lists = new ArrayList<>();
public List<List> combinationSum(int[] candidates, int target) {

    return lists;
}

}
Look at the returned structure, List <List>. Therefore, we need to write an auxiliary function containing List, plus some judgment conditions, and the structure becomes

class Solution {
List<List> lists = new ArrayList<>();
public List<List> combinationSum(int[] candidates, int target) {
if (candidates == null || candidates.length == 0 || target < 0) {
return lists;
}

    List<Integer> list = new ArrayList<>();
    process(candidates, target, list);
    return lists;
}

private void process(int[] candidates, int target, List<Integer> list) {


}

} The
point is how to recurse. The first step of recursion is, of course, to write the termination condition of recursion. Recursion without termination condition will enter an endless loop. So what are the termination conditions? Because the conditions are all positive integers. Therefore, if target <0, of course, it must be terminated. If target == 0, it means that the sum of a set of numbers is found at this time, and it is added. At this point the code structure becomes like this.

class Solution {
List<List> lists = new ArrayList<>();
public List<List> combinationSum(int[] candidates, int target) {
if (candidates == null || candidates.length == 0 || target < 0) {
return lists;
}

    List<Integer> list = new ArrayList<>();
    process(candidates, target, list);
    return lists;
}

private void process(int[] candidates, int target, List<Integer> list) {
    if (target < 0) {
        return;
    }
    if (target == 0) {
        lists.add(new ArrayList<>(list));
    }
   

}

}
We are asking for a combination of targets. Therefore, a loop is needed to traverse. Each traversal, add this number to the list, and then perform the next round of recursion. The code structure is as follows.

class Solution {
List<List> lists = new ArrayList<>();
public List<List> combinationSum(int[] candidates, int target) {
if (candidates == null || candidates.length == 0 || target < 0) {
return lists;
}

    List<Integer> list = new ArrayList<>();
    process(candidates, target, list);
    return lists;
}

private void process(int[] candidates, int target, List<Integer> list) {
    if (target < 0) {
        return;
    }
    if (target == 0) {
        lists.add(new ArrayList<>(list));
    } else {
        for (int i = 0; i < candidates.length; i++) {
            list.add(candidates[i]);
            //因为每个数字都可以使用无数次,所以递归还可以从当前元素开始
            process( candidates, target - candidates[i], list);
  
        }
    }

}

}
It seems to take shape, the test results are as follows

As a result, the gap is a bit large, why is there such a big contrast. And found a rule, the latter combination will contain all the numbers of the previous combination, and the sum of these numbers is not equal to the target. What is the reason? In addition to a few basic types in Java, other types can be counted as passing by reference. This is what causes the list number to keep increasing. Therefore, after each recursion is completed, we have to perform a backtracking. Delete the latest added number. At this point the code structure becomes like this.

class Solution {
List<List> lists = new ArrayList<>();
public List<List> combinationSum(int[] candidates, int target) {
if (candidates == null || candidates.length == 0 || target < 0) {
return lists;
}

    List<Integer> list = new ArrayList<>();
    process(candidates, target, list);
    return lists;
}

private void process(int[] candidates, int target, List<Integer> list) {
    if (target < 0) {
        return;
    }
    if (target == 0) {
        lists.add(new ArrayList<>(list));
    } else {
        for (int i = 0; i < candidates.length; i++) {
            list.add(candidates[i]);
            //因为每个数字都可以使用无数次,所以递归还可以从当前元素开始
            process( candidates, target - candidates[i], list);
            list.remove(list.size() - 1);
        }
    }

}

}
Test again, the results are as follows:

Still wrong. This time it adds up to 7 and it is a big improvement from the last result. Analyze the test results. It is not difficult to see that the main problem of this result involves repeated combinations. Why are there repeated combinations? Because each recursion starts from 0, all numbers are traversed again. So there will be repeated combinations. To improve, just add a start variable. talk is cheap, show me the code.

code show as below:

List<List> lists = new ArrayList<>();

public List<List<Integer>> combinationSum(int[] candidates, int target) {
    if (candidates == null || candidates.length == 0 || target < 0) {
        return lists;
    }

    List<Integer> list = new ArrayList<>();
    process(0, candidates, target, list);
    return lists;
}

private void process(int start, int[] candidates, int target, List<Integer> list) {
    //递归的终止条件
    if (target < 0) {
        return;
    }
    if (target == 0) {
        lists.add(new ArrayList<>(list));
    } else {
        for (int i = start; i < candidates.length; i++) {
            list.add(candidates[i]);
            //因为每个数字都可以使用无数次,所以递归还可以从当前元素开始
            process(i, candidates, target - candidates[i], list);
            list.remove(list.size() - 1);
        }
    }

}

Finally, test again.

The code passes, but the efficiency is not high. This question has a better solution for dynamic programming. This article mainly shows recursive backtracking, so I won't introduce it in detail.

7

40. Combined Sum II

Given an array of candidates and a target number target, find all combinations in the candidates that can make the number sum target.

Each number in candidates can only be used once in each combination.

Description:

All numbers (including the target number) are positive integers.
The solution set cannot contain duplicate combinations.
Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
the solved set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
Example 2:

Input: candidates = [2,5,2,1,2], target = 5,
the solved set is:
[
[1,2,2],
[5]
]

Idea: The difference between this question and the previous one is that the numbers used in the same search can no longer be used, so here every time the downward search table is incremented by 1, and when the sum is equal, it is judged whether to repeat, if it is repeated, skip , Otherwise join the collection

class Solution {
    List<List<Integer>> lists = new ArrayList<>();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        if(candidates==null||candidates.length==0||target<0){
            return lists;
        }
        Arrays.sort(candidates);
        List<Integer> list = new ArrayList<>();
        dfs(candidates,0,target,list);
        return lists;
    }

    public void dfs(int[] candidates,int start,int target,List<Integer> list){
        if(target<0)
        return;
        if(target==0){
            if(!lists.contains(list))
            lists.add(new ArrayList<>(list));
            return;
        }
        for(int i=start;i<candidates.length;i++){
            list.add(candidates[i]);
            dfs(candidates,i+1,target-candidates[i],list);
            list.remove(list.size()-1);
        }
    }
}

8

216. Combination Sum III

Find all combinations of k numbers whose sum is n. Only positive integers from 1 to 9 are allowed in the combination, and there are no duplicate numbers in each combination.

Description:

All numbers are positive integers.
The solution set cannot contain duplicate combinations.
Example 1:

Input: k = 3, n = 7
Output: [[1,2,4]]
Example 2:

Input: k = 3, n = 9
Output: [[1,2,6], [1,3,5], [2,3,4]]

Idea: This question is similar to the sixth question, the point is that the array used is given by yourself, between 1-9, and cannot be used repeatedly in the same search, so we add 1 to the index subscript in each search After the operation, delete and roll back.

class Solution {
    List<List<Integer>> lists = new ArrayList<>();
    public List<List<Integer>> combinationSum3(int k, int n) {
        if(k*9<n)
        return lists;
        dfs(k,1,n,new ArrayList<>());
        return lists;
    }

    public void dfs(int k,int start,int n,List<Integer> list){
        if(n<0)
        return ;
        if(n==0){
            if(list.size()==k)
            lists.add(new ArrayList<>(list));
            return;
        }
        for(int i=start;i<=9;i++){
            list.add(i);
            dfs(k,i+1,n-i,list);
            list.remove(list.size()-1);
        }
    }
}

9

377. Combined sum IV

Given an array of positive integers and no duplicate numbers, find the number of combinations of positive integers for the given target.

Example:

nums = [1, 2, 3]
target = 4

All possible combinations are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1 )

Please note that sequences in different orders are considered as different combinations.

class Solution {
        //递归超时,这里使用dp思想
       public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target + 1];
        // 这个值被其它状态参考,设置为 1 是合理的
        dp[0] = 1;

        for (int i = 1; i <= target; i++) {
            for (int num : nums) {
                if (num <= i) {
                    dp[i] += dp[i - num];
                }
            }
        }
        return dp[target];
    }
}




So the output is 7.

10

Published 4 original articles · liked 0 · visits 16

Guess you like

Origin blog.csdn.net/smile_study1/article/details/105600456