每日算法

跳台阶问题

问题描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

测试用例

输入:3
返回值:4

解决思路

转换为数学问题:

在这里插入图片描述

AC
java
public class Solution {
    public int jumpFloorII(int target) {
        //f(1)=1,f(n)=pow(2,n-1)
        return target <= 0 ? 0 : 1 << (target - 1);
    }
}
python
# -*- coding:utf-8 -*-
class Solution:
    def jumpFloorII(self, number):
        # write code here
        return number if number<=1 else pow(2, number-1)

生成格雷码

问题描述

在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同, 则称这种编码为格雷码(Gray Code),请编写一个函数,使用递归的方法生成N位的格雷码。

给定一个整数n,请返回n位的格雷码,顺序为从0开始。

测试用例
输入:1
返回:["0","1"]
解决思路

递归实现:

首先可以看出,n位有2^n个格雷码;

递归结束条件,n=1时,返回的是[‘0’,‘1’];

返回上一次,在n=2时,在n=1的基础上,每个结果上面分别加上0和1,构成n=2的结果;

由此可见,本次的结果,都是上一次结果的基础上,每个结果首位加0和1;

AC
java
import java.util.*;

public class GrayCode {
    public String[] getGray(int n) {
        // write code here
        String[] fr = new String[(int) Math.pow(2,n)];
        if(n==1){
            fr[0]="0";
            fr[1]="1";
            return fr;
        }
        fr = getGray(n-1);
        String[] res = new String[2*fr.length];
        for (int i = 0; i < fr.length; i++) {
            res[i]="0"+fr[i];
            res[fr.length+i]="1"+fr[fr.length-1-i];
        }
        return res;
    }
}
python
class GrayCode:
    def getGray(self, n):
        if n==1:
            return ['0','1']
        res = self.getGray(n-1)
        fr = []
        len_res = len(res)
        for i in res:
            fr.append('0'+i)
        #这里注意倒序,因为要保证相邻两位代码,只有1位不相同
        for i in range(len_res-1,-1,-1):
            fr.append('1'+res[i])
        return fr


微信红包

问题描述

春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。

给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。

若没有金额超过总数的一半,返回0。

测试用例
输入:[1,2,3,2,2],5
返回:2
解决思路

利用map数据结构进行操作,key的value超过一半,就return key;

AC
java
import java.util.*;

public class Gift {
    public int getValue(int[] gifts, int n) {
        // write code here
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int x:gifts) {
            if(map.containsKey(x)){
                map.put(x,map.get(x)+1);
                if(map.get(x)>(n/2)){
                    return x;
                }
            }else{
                map.put(x,1);
            }
        }
        return 0;
    }
}
python
class Gift:
    def getValue(self, gifts, n):
        # write code here
        dic= dict()
        for i in gifts:
            if i in dic.keys():
                dic[i] += 1
                if dic[i]>n/2:
                    return i
            else:
                dic[i]=1
        return 0

子集

问题描述

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集

测试用例

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:

输入:nums = [0]
输出:[[],[0]]

解决思路
AC
python
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res,path=[],[]
        self.dfs(nums,0,res,path)
        return res
    
    def dfs(self,nums,index,res,path):
        #一个path就是一个解
        res.append(copy.deepcopy(path))
        for i in range(index,len(nums)):
            path.append(nums[i])
            self.dfs(nums,i+1,res,path)
            path.pop()

子集2

问题描述

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

测试用例

示例 1:

输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:

输入:nums = [0]
输出:[[],[0]]

解决思路

回溯法类似,与之前的区别在于存在重复整数,需要先对原数组进行排序,然后再开始回溯;

AC
java
public  List<List<Integer>> res = new ArrayList<List<Integer>>();
    public  List<Integer> t = new ArrayList<Integer>();
    public  List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        dfs(nums,0);
        return res;
    }
    public void dfs(int[] nums,int index){

        if (index==nums.length){
            res.add(new ArrayList<Integer>(t));
            return;
        }
        if (!res.contains(t)){
            res.add(new ArrayList<Integer>(t));
        }
        for (int i = index; i < nums.length; i++) {
            if (i>index&&(nums[i]==nums[i-1])){
                continue;
            }
            t.add(nums[i]);
            dfs(nums,i+1);
            t.remove(t.size()-1);
        }

    }
python
class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        res,path=[],[]
        nums.sort()
        self.dfs(nums,0,res,path)
        return res
            
    def dfs(self,nums,index,res,path):
        if path not in res:
            res.append(path)
        for i in range(index, len(nums)):
            if i > index and nums[i] == nums[i - 1]:
                continue
            self.dfs(nums, i + 1, res, path + [nums[i]])

最长公共子序列

问题描述

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

测试用例

示例 1:

输入:text1 = “abcde”, text2 = “ace”
输出:3
解释:最长公共子序列是 “ace” ,它的长度为 3 。
示例 2:

输入:text1 = “abc”, text2 = “abc”
输出:3
解释:最长公共子序列是 “abc” ,它的长度为 3 。
示例 3:

输入:text1 = “abc”, text2 = “def”
输出:0
解释:两个字符串没有公共子序列,返回 0 。

提示:

1 <= text1.length, text2.length <= 1000
text1 和 text2 仅由小写英文字符组成。

解决思路

**动态规划题目:**典型二维动态规划问题;

text1的长度为m,text2的长度为n,创建m+1行,n+1列的二维数组dp,其中的dp[i] [j]表示text1[0:i]和text2[0:j]的最长公共子序列的长度

动态规划的边界情况:

当 i=0i=0 时,text 1 [0:i] 为空,空字符串和任何字符串的最长公共子序列的长度都是 0,因此对任意 j,有dp[0] [j] =0;

当 j=0j=0 时,text 2 [0:j] 为空,同理可得,对任意i,有 dp[i] [0] = 0。

因此动态规划的边界情况是:当 i=0 或 j=0 时,dp[i] [j]=0。

在这里插入图片描述

AC
java
class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int m = text1.length();
        int n = text2.length();
        int [][] dp = new int[m+1][n+1];
        for (int i = 1; i <=m ; i++) {
            for (int j = 1; j <=n ; j++) {
                if (text1.charAt(i-1)==text2.charAt(j-1)){
                    //更新状态方程
                    dp[i][j] = dp[i-1][j-1]+1;
                }else{
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                }
            }


        }
        return dp[m][n];

    }
}

全排列

问题描述

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

测试用例

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

解决思路

回溯法:到底的每条路径即为一种可能的排列,可以结合树来思考问题,找出循环以及结束的调价;

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。

AC
python
class Solution:
    
    def permute(self, nums: List[int]) -> List[List[int]]:
        res = []
        def dfs(num,li,depth,unsigned,path):
            if depth==num:
                nonlocal res
                res.append(copy.deepcopy(path))
            for i in range(num):
                if unsigned[i]!=0:
                    continue
                path.append(li[i])
                unsigned[i]=1
                dfs(num,li,depth+1,unsigned,path)
                path.remove(li[i])
                unsigned[i]=0
        used = [0]*len(nums)
        dfs(len(nums),nums,0,used,[])
        return res

最长递增子序列

问题描述

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

测试用例
示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4		
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:
输入:nums = [7,7,7,7,7,7,7]
输出:1
解决思路

动态规划:定义状态,找出状态转化方程,状态初始化;

定义dp[n]数字,状态dp[i]表示到num[i]为止,最长上升子序列的长度;

dp[i] = max(dp[j])+1,0<j<i,并且保证组成上升子序列num[i]>num[j];

最后所求结果为dp[]数组的最大值;

AC
python
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        dp = [1]*len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if nums[i]>nums[j]:
                    dp[i] = max(dp[i],dp[j]+1)


        return max(dp)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值