46:
回溯法:
为了避免结果集重复,采用回溯法。构造一个新数组tmp,将nums中元素改变位置后,首先放入一个tmp中,再将tmp插入结果集中。在完成当前顺序插入,退回上一步时,需要将上一步的结果回溯掉,将nums复原。
如上1 2 3,首先应该将1, 2, 3插入结果集,然后交换2, 3的位置。每一层都是一个递归。那么就需要一个位置指针pos,这个指针表示,需要从当前元素开始替换,一直替换到最后一个。
如何结束回溯:当我们的位置下标等于所给num长度,即递归完毕。
Pos相当于递归的层数,同时也是需要置换的元素的位置。注意每次添加的是pos和i置换后的pos位元素。
//之所以这么做 是因为 每个数字只和位于他后头的数字作交换
47:
上一题中题目所给元素均为不重复,下一题中题目所给元素为可能重复元素:
接下来看60
这道题 同样是置换 如果用回溯,会死的很惨。
结果上千毫秒。 那么这题,只能另寻他法。其实此题可以使用一种规律方法。
例如: 每一个数字作为第一个数字时置换的次数都是(n-1)!次
如:
1 + (2, 3, 4) 置换
2 + (1, 3, 4) 置换
3 + (1, 2, 4) 置换
4 + (1, 2, 3) 置换
1, 2, 3, 4 每个数字分别都有(4 - 1)!次 。 再乘以n个数字 就是第n个数字一共可以的置换次数。
那么根据这个规律 不难凑出第k个数字。 如k=14时, 我们知道n=4时 一共有4 × 6 = 24次置换
那么1有6次 2有6次 余2 14 = 6 + 6 + 2 所以可知第一个数字为3。
77题还可以沿用之前的套路,只不过将数组换位了数字,并且递归条件发生变化,本来是pos + 1,此处访问过的数字便不再访问,所以pos + 1直接改为i + 1
简化算法:
模板(来自leetcode大神):