目录
- 全排列
- 全排列 II
- 旋转图像
- 字母异位词分组
- Pow(x, n)
46. 全排列
题目描述
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2],[3,2,1] ]
思路:
(回溯) O(n×n!) 我们从前往后,一位一位枚举,每次选择一个没有被使用过的数。
选好之后,将该数的状态改成“已被使用”,同时将该数记录在相应位置上,然后递归。
递归返回时,不要忘记将该数的状态改成“未被使用”,并将该数从相应位置上删除。
c++代码
class Solution {
public:
vector<vector<int>>ans;
vector<int>path;
vector<bool>visted;
vector<vector<int>> permute(vector<int>& nums) {
int n = nums.size();
// path=vector<int>(n);
visted=vector<bool>(n);
dfs(nums,0);
return ans;
}
void dfs(vector<int>& nums,int cur)
{
if(cur==nums.size())
{
ans.push_back(path);
return;
}
for(int i =0;i<nums.size();i++)
{
if(!visted[i])
{
visted[i]=true;
path.push_back(nums[i]);
dfs(nums,cur+1);
visted[i]=false;
path.pop_back();
}
}
}
};
python代码
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
visted= [False] * len(nums)
path = [0] * len(nums)
ans = []
def dfs(nums, cur):
if(cur == len(nums)):
ans.append(path[::])
return
for i in range(len(nums)):
if(not visted[i]):
visted[i] = True
path[cur] = nums[i]
dfs(nums, cur + 1)
visted[i] = False
dfs(nums, 0)
return ans
47. 全排列 II
题目描述
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出: [ [1,1,2], [1,2,1], [2,1,1] ]
思路
在上一题的基础上剪枝
对nums[i]升序排序,选择nums[i]作为递归搜索树的当前节点时,发现nums[i]==nums[i-1]存在以下两种情况
(1)若nums[i-1]的状态刚刚恢复(visted[i-1]=true),说明nums[i-1]与num[i]在递归树中属于同一层的相邻状态结点而这数值相等会产生重复的递归实例,故在num[i]结点处进行剪枝回溯
(2)nums[i-1]状态还未恢复(visted[i-1]=false),说明nums[i-1]与nums[i]在递归树中属于同一路径的上下层, 二者数值相等不会产生重复递归实例。
c++代码
class Solution {
public:
vector<vector<int>>ans;
vector<int>path;
vector<bool>visted;
vector<vector<int>> permuteUnique(vector<int>& nums) {
int n = nums.size();
//path=vector<int>(n);
visted=vector<bool>(n);
sort(nums.begin(), nums.end());
dfs(nums,0);
return ans;
}
void dfs(vector<int>& nums,int cur)
{
if(cur==nums.size())
{
ans.push_back(path);
return;
}
for(int i =0;i<nums.size();i++)
{
if(!visted[i])
{
if(i>0&&!visted[i-1]&&nums[i]==nums[i-1])
continue;
visted[i]=true;
path.push_back(nums[i]);
dfs(nums,cur+1);
visted[i]=false;
path.pop_back();
}
}
}
};
python代码
class Solution(object):
def permuteUnique(self, nums):
ans = []
path = [0] * len(nums)
st = [False] * len(nums)
def dfs(nums, cur):
if cur == len(nums):
ans.append(path[::])
return
for i in range(len(nums)):
if not st[i]:
if i > 0 and nums[i] == nums[i - 1] and not st[i - 1]:
continue
st[i] = True
path[cur] = nums[i]
dfs(nums, cur + 1)
st[i] = False
nums.sort()
dfs(nums, 0)
return ans
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
48. 旋转图像
给定一个 n × n 的二维矩阵表示一个图像。 将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:
给定 matrix = [
[1,2,3],
[4,5,6],
[7,8,9] ], 原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
示例 2:
给定 matrix = [
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
], 原地旋转输入矩阵,使其变为:
[ [15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]
思路
(操作分解) O(n2)
直接操作旋转 90 度比较困难,我们可以将它分解成两个操作: 先以左上-右下对角条线为轴做翻转;
再以中心的竖线为轴做翻转;
c++代码
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
for(int i = 0; i < matrix[0].size(); i++)
for(int j = i + 1; j < matrix[0].size(); j++)
swap(matrix[i][j], matrix[j][i]);//左上角和右下角交换
for(int i = 0; i < matrix[0].size(); i++)
for(int j = 0, k = matrix[0].size() - 1; j < k; j++, k--)
swap(matrix[i][j], matrix[i][k]);
}
};
python代码
class Solution(object):
def rotate(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: None Do not return anything, modify matrix in-place instead.
"""
n = len(matrix[0])
for i in range(n):
for j in range(i + 1, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
for i in range(n):
j = 0
k = n - 1
while j < k:
matrix[i][j], matrix[i][k] = matrix[i][k], matrix[i][j]
j += 1
k -= 1
49. 字母异位词分组
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [
[“ate”,“eat”,“tea”], [“nat”,“tan”], [“bat”] ]
说明:
所有输入均为小写字母。 不考虑答案输出的顺序。
c++代码
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>>hash;
vector<vector<string>>res;
for(auto str:strs)
{
string key = str;
sort(key.begin(),key.end());
hash[key].push_back(str);
}
for(auto i =hash.begin();i!=hash.end();i++)
{
res.push_back(i->second);
}
return res;
}
};
python代码
class Solution(object):
def groupAnagrams(self, strs):
Hash = {}
for s in strs:
key = ''.join(sorted(list(s)))
if Hash.get(key) is not None:
Hash[key].append(s)
else:
Hash[key] = [s]
return list(Hash.values())
"""
:type strs: List[str]
:rtype: List[List[str]]
"""
50. Pow(x, n)
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:
输入: 2.00000, 10 输出: 1024.00000
示例 2:
输入: 2.10000, 3 输出: 9.26100
示例 3:
输入: 2.00000, -2 输出: 0.25000 解释: 2-2 = 1/22 = 1/4 = 0.25
思路
我们可以利用指数函exp和对数函数ln来巧妙转换。我们将x^n用自然对数e换底,即可得到:
x^n = e^{nlnx}
需要注意的是x取负值的时候,需要进行判断。
1.当x < 0 && n % 2 == 0 时,只需将对数函数中的x取绝对值。
2.当x < 0 && n % 2 == 1 时,需将对数函数中的x取绝对值,同时整体取负值。
c++代码
class Solution {
public:
double myPow(double x, int n) {
if(x==0) return 0;
double ans;
if(x>0||(x<0&&(n%2==0))) ans = exp(n*log(abs(x)));
else ans = -exp(n*log(abs(x)));
return ans;
}
};
python代码
class Solution(object):
def myPow(self, x, n):
if x>0 or (x<0 and n%2==0):
ans = math.exp(n*math.log(abs(x)))
else:
ans = -math.exp(n*math.log(abs(x)))
return ans
"""
:type x: float
:type n: int
:rtype: float
"""