LeetCode 算法系列:第 46 ~50题

目录

  1. 全排列
  2. 全排列 II
  3. 旋转图像
  4. 字母异位词分组
  5. 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
        """
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值