46&&47.Permutations I&&II && 40 .Combination Sum II(回溯)

Permutations I

Given a collection of distinct numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].

 

class Solution {
 private:
     vector<vector<int>> res;
 public:
     void getPer(vector<int>&nums,int index,int lenth)
     {
         if(index==lenth)
             res.push_back(nums);
         int temp;
         for(int i=index;i<lenth;i++)
         {
             temp=nums[i];
             nums[i]=nums[index];
             nums[index]=temp;
             getPer(nums,index+1,lenth);
             temp= nums[i];
             nums[i]=nums[index];
             nums[index]=temp;
         }
         return ;
     }
     vector<vector<int>> permute(vector<int>& nums) {
         getPer(nums,0,nums.size());
         return res;
         
    }
 };

Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1].

这道题其实也纠结了我很久。没想到只需要定义一个set来存储已经交换过的元素值就可以把问题完美的解决了。

class Solution {
public:
    vector<vector<int> > permuteUnique(vector<int> &num) {
        if(num.size() <= 0) return res;
        permCore(num, 0);
        return res;
    }
private:
    vector<vector<int> > res;
    void permCore(vector<int> &num, int st){
        if(st == num.size()) res.push_back(num);
        else{
            set<int> swp;
            for(int i = st; i < num.size(); ++i){
                if(swp.find(num[i]) != swp.end()) continue;
                swp.insert(num[i]);
                swap(num, st, i);
                permCore(num, st+1);
                swap(num, st, i);
            }
        }
    }
    
    void swap(vector<int> &num, int left, int right){
        int tmp = num[left];
        num[left] = num[right];
        num[right] = tmp;
    }
};

 

II:

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
  • The solution set must not contain duplicate combinations.

 

For example, given candidate set 10,1,2,7,6,1,5 and target 8
A solution set is: 
[1, 7] 
[1, 2, 5] 
[2, 6] 
[1, 1, 6]

复制代码
class Solution {
private:
    vector<vector<int>> res;
    vector<int> temp;
public:
    void combinationSum(vector<int>& candidates, int target,vector<int>::iterator initer,int tempsum)
    {
      if(tempsum==target)
      {
            if(find(res.begin(),res.end(),temp)==res.end())
                res.push_back(temp);
            return ;
      }
      if(initer==candidates.end()||tempsum>target)
            return ;
      for(vector<int>::iterator iter=initer;iter!=candidates.end();iter++)
      {
            temp.push_back(*iter);
            combinationSum(candidates,target,iter+1, tempsum+*iter);
            temp.pop_back();
           
     }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
        vector<int>::iterator initer=candidates.begin();
        combinationSum(candidates,target,initer,0);
        return res;
        
        
    }
};
  
复制代码

 

方法二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Solution {
public:
    vector<int> singleRes;
    vector<vector<int>> res;
    void judgeSubSum(vector<int>& candidates, int target,int index)
    {
        if(target < 0)
        {
            return;
        }
 
        if(target == 0)
        {
            res.push_back(singleRes);
            return;
        }
        int len= candidates.size();
        for(int i = index; i <len; i++)
        {
            if(i>index&& candidates[i] == candidates[i-1])
            {
                continue;
            }
            int val = candidates[i];
            singleRes.push_back(val);
            judgeSubSum(candidates, target - val,i+1);
            singleRes.pop_back();
        }
     
        return;
 
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        int len= candidates.size();
        sort(candidates.begin(), candidates.end());
        for(int i = 0; i <len; i++)
        {
            if(i>0&& candidates[i] == candidates[i-1])
            {
                continue;
            }
            int val = candidates[i];
            singleRes.push_back(val);
            judgeSubSum(candidates, target - val,i+1);
            singleRes.pop_back();
        }
        return res;
 
    }
};

  

解释语句: if cur > begin and candidates[cur-1] == candidates[cur] 是如何避免重复的。


这个避免重复当思想是在是太重要了。
这个方法最重要的作用是,可以让同一层级,不出现相同的元素。即
                  1
                 / \
                2   2  这种情况不会发生 但是却允许了不同层级之间的重复即:
               /     \
              5       5
                例2
                  1
                 /
                2      这种情况确是允许的
               /
              2  
                
为何会有这种神奇的效果呢?
首先 cur-1 == cur 是用于判定当前元素是否和之前元素相同的语句。这个语句就能砍掉例1。
可是问题来了,如果把所有当前与之前一个元素相同的都砍掉,那么例二的情况也会消失。 
因为当第二个2出现的时候,他就和前一个2相同了。
                
那么如何保留例2呢?
那么就用cur > begin 来避免这种情况,你发现例1中的两个2是处在同一个层级上的,
例2的两个2是处在不同层级上的。
在一个for循环中,所有被遍历到的数都是属于一个层级的。我们要让一个层级中,
必须出现且只出现一个2,那么就放过第一个出现重复的2,但不放过后面出现的2。
第一个出现的2的特点就是 cur == begin. 第二个出现的2 特点是cur > begin.
posted @ 2015-05-27 16:19  linqiaozhou  阅读(280)  评论(0编辑  收藏  举报