47. The power button LeetCode full array II

Title Description (medium difficulty)

And on a question similar, the difference is that there will be a given number of repeat, this is the case with the previous algorithm will yield repeat sequences. For example, [11], with the previous algorithm, the result is affirmative [[11], [11]], which is produced repeat sequences. But we can be modified in a solution of the problem in order to address this question.

Solution insert a

This did not think how to change based on the original, some may be straightforward, in the results it produces, the de-emphasis on the results back. For deduplication, the general approach is to write certainly for two cycles, and then compared with each other one by one, and then find duplicates removed. Here, we use 39 questions a method of de-duplication solution II mentioned.

public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> all = new ArrayList<>(); 
    List<Integer> temp = new ArrayList<>();
    temp.add(nums[0]);
    all.add(temp); 
    for (int i = 1; i < nums.length; i  ) {
        int current_size = all.size();
        for (int j = 0; j < current_size; j  ) {
            List<Integer> last = all.get(j);
            for (int k = 0; k <= i; k  ) {
                if (k < i && nums[i] == last.get(k)) {
                    continue;
                }
                temp = new ArrayList<>(last);
                temp.add(k, nums[i]);
                all.add(temp);
            }
        }
        for (int j = 0; j < current_size; j  ) {
            all.remove(0);
        }
    }
    return removeDuplicate(all);
}

private List<List<Integer>> removeDuplicate(List<List<Integer>> list) {
    Map<String, String> ans = new HashMap<String, String>();
    for (int i = 0; i < list.size(); i  ) {
        List<Integer> l = list.get(i);
        String key = "";
        // [ 2 3 4 ] 转为 "2,3,4"
        for (int j = 0; j < l.size() - 1; j  ) {
            key = key   l.get(j)   ",";
        }
        key = key   l.get(l.size() - 1);
        ans.put(key, "");
    }
    // 根据逗号还原 List
    List<List<Integer>> ans_list = new ArrayList<List<Integer>>();
    for (String k : ans.keySet()) {
        String[] l = k.split(",");
        List<Integer> temp = new ArrayList<Integer>();
        for (int i = 0; i < l.length; i  ) {
            int c = Integer.parseInt(l[i]);
            temp.add(c);
        }
        ans_list.add(temp);
    }
    return ans_list;
}

Solution two back

Before facie algorithm

public List<List<Integer>> permute(int[] nums) {
    List<List<Integer>> list = new ArrayList<>(); 
    backtrack(list, new ArrayList<>(), nums);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
    if(tempList.size() == nums.length){
        list.add(new ArrayList<>(tempList));
    } else{
        for(int i = 0; i < nums.length; i  ){ 
            if(tempList.contains(nums[i])) continue; // 已经存在的元素,跳过
            tempList.add(nums[i]); //将当前元素加入
            backtrack(list, tempList, nums); //向后继续添加
            tempList.remove(tempList.size() - 1); //将 tempList 刚添加的元素,去掉,尝试新的元素
        }
    }
}

If given array is [113], we look at this graph traversal.

The first to be solved is this code

if(tempList.contains(nums[i])) continue; // 已经存在的元素,跳过

Before no duplicate elements, so you can directly templist judgment there is no current element, any skipped. But here, it has since given repeated elements, this approach obviously can not do that.

A change in thinking, and then we can save a list templist has some elements of the current index and then add a new element to judge when the index it.

The second problem is that there are duplicate elements can be seen, when the upper side of FIG. 1 and FIG. 2 is generated in exactly the same sequence. So the first two traverse is not necessary.

The solution is to put arrays arranged for the first order, and then determine what elements and add on a current element is not equal, equal, then skip, continue to the next element.

public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    List<Integer> old = new ArrayList<>();
    backtrack(list, new ArrayList<>(), nums, old);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums, List<Integer> old) {
    if (tempList.size() == nums.length) {
        list.add(new ArrayList<>(tempList));
    } else {
        for (int i = 0; i < nums.length; i  ) { 
            //解决第一个问题
            if (old.contains(i)) {
                continue;
            }
            //解决第二个问题 !old.contains(i - 1) 很关键,下边解释下
            if (i > 0 && !old.contains(i - 1) && nums[i - 1] == nums[i]) {
                continue;
            }
            old.add(i);//添加下标
            tempList.add(nums[i]); // 将当前元素加入
            backtrack(list, tempList, nums, old); // 向后继续添加
            old.remove(old.size() - 1);
            tempList.remove(tempList.size() - 1);
        }
    }
}

Solve the second problem old.contains! (I - 1) is critical
because the top old.contains (i) code so that no skipped some elements added to the templist, so we have to judge nums [i - 1] is not being skipped that element, if old.contains (i) returns true, even nums [i - 1] == nums [i] can not skip the current element. Since one element nums [i - 1] was not added to templist. May be more around, but can refer to the top of the chart, go about the process to understand. If not old.contains (i - 1)!, Then the second row of FIG. 1 in the first two should have been added tempList, but will be skipped. Because row 2, one element is 1.

For solve the first problem, we used a list to hold the index to resolve. We need a space O (n) a. Is there a way we can space O (1) with. But the premise is that we need to sample understanding of the problem, that is a given digital input included. We need to find a digital sample does not contain a certain to solve our problems.

First, we assume that all of the digital input that number is not -100.

Then, before we can recursively be saved before the current number, then set -100 hidden after the recursive reduction can be.

public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums); 
    backtrack(list, new ArrayList<>(), nums);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums) {
    if (tempList.size() == nums.length) {
        list.add(new ArrayList<>(tempList));
    } else {
        for (int i = 0; i < nums.length; i  ) { 
            //解决第一个问题
            if (nums[i] == -100) {
                continue;
            }
            //解决第二个问题 !old.contains(i - 1) 很关键 
            if (i > 0 && nums[i-1] != -100 && nums[i - 1] == nums[i]) {
                continue;
            }
            tempList.add(nums[i]); // 将当前元素加入 
            int temp = nums[i]; //保存
            nums[i] = -100; // 隐藏
            backtrack(list, tempList, nums); // 向后继续添加
            nums[i] = temp; //还原
            tempList.remove(tempList.size() - 1);
        }
    }
}

Of course, this idea of ​​a great limitations, but if you are familiar with problem solving, usually can not find such a digital input, you can then optimize space complexity.

Solution three exchange

This change is relatively easier, before the idea is in every position, so that each number in turn exchange about the past. Here, then, in fact, as long as the current position we have been saved numbers to which, if repeated, we would not let him exchange, directly replaced a number on it.

public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> all = new ArrayList<>();
    Arrays.sort(nums);
    upset(nums, 0, all);
    return all;
}

private void upset(int[] nums, int begin, List<List<Integer>> all) {
    if (begin == nums.length) {
        ArrayList<Integer> temp = new ArrayList<Integer>();
        for (int i = 0; i < nums.length; i  ) {
            temp.add(nums[i]);
        }
        all.add(new ArrayList<Integer>(temp));
        return;
    }
    HashSet<Integer> set = new HashSet<>(); //保存当前要交换的位置已经有过哪些数字了
    for (int i = begin; i < nums.length; i  ) {
        if (set.contains(nums[i])) { //如果存在了就跳过,不去交换
            continue;
        }
        set.add(nums[i]);
        swap(nums, i, begin);
        upset(nums, begin   1, all);
        swap(nums, i, begin);
    }

}

private void swap(int[] nums, int i, int begin) {
    int temp = nums[i];
    nums[i] = nums[begin];
    nums[begin] = temp;
}

total

Basically change on the basis of questions on it, and some skills are often encountered, such as the first sort, and then determine whether to repeat the previous one. Hash function to re-use. Using the original data storage space hidden away, then think of ways to restore.

For more detailed explanations of popular leetcode.wang .

Published 61 original articles · won praise 7 · views 20000 +

Guess you like

Origin blog.csdn.net/wind_liang/article/details/104039016