【面试算法题总结13】贪心算法

贪心算法:

 

例题1:剪绳子

class Solution {
    public int cuttingRope(int n) {
        if(n<=3){
            return n-1;
        }
        int a=n/3;
        int b=n%3;
        if(b==0){
            return (int)Math.pow(3,a);
        }else if(b==1){
            return (int)Math.pow(3,a-1)*4;
        }else{
            return (int)Math.pow(3,a)*2;
        }
    }
}

 

例题2:剪绳子 II

(1)因为n太大了,所以在动态规划的基础上取余,就算把数据类型都换成long也是无解的,对每次的dp[i]取余确实可以避免溢出的问题,但是由于过程中修改了值,会导致最终结果和预期不同。比如这一步:dp[i] = Math.max(dp[i] ,x * y );
因此只能用大数类型
(2)贪心法也不能直接用Math.pow也会超Double范围。而要自己定义一个long变量,自己做乘法并求余

class Solution {
    public int cuttingRope(int n) {
        if(n<=3){
            return n-1;
        }
        int a=n/3;
        int b=n%3;
        //为了应对n过大的问题
        long temp=1L;
        for(int i=0;i<a-1;++i){
            temp=temp*3%1000000007;
        }
        if(b==0){
            return (int)(temp*3%1000000007);
        }else if(b==1){
            return (int)(temp*4%1000000007);
        }else{
            return (int)(temp*3*2%1000000007);
        }
    }
}

 

例题3:剪绳子(进阶版)

n过于大了,要加上快速幂算法,不然超时。

import java.util.*;


public class Solution {
    //n不为负数的快速幂算法,并求余
    public long myPow (long x,long n) {
        long result=1L;
        while(n>0){
            if(n%2==1){
                result=result*x%998244353;
            }
            x=x*x%998244353;
            n/=2;
        }
        return result;
    } 
    public long cutRope (long number) {
        if(number<=3){
            return number-1;
        }
        long a=number/3;
        long b=number%3;
        //为了应对n过大的问题,并采用快速幂减低时间复杂度
        long temp=myPow(3,a-1);
        if(b==0){
            return (long)(temp*3%998244353);
        }else if(b==1){
            return (long)(temp*4%998244353);
        }else{
            return (long)(temp*3*2%998244353);
        }
    }
    
}

 

例题4:任务调度器

class Solution {
    public int leastInterval(char[] tasks, int n) {
        Map<Character, Integer> freq = new HashMap<Character, Integer>();
        // 最多的执行次数
        int maxExec = 0;
        for (char ch : tasks) {
            int exec = freq.getOrDefault(ch, 0) + 1;
            freq.put(ch, exec);
            maxExec = Math.max(maxExec, exec);
        }

        // 具有最多执行次数的任务数量
        int maxCount = 0;
        Set<Map.Entry<Character, Integer>> entrySet = freq.entrySet();
        for (Map.Entry<Character, Integer> entry : entrySet) {
            int value = entry.getValue();
            if (value == maxExec) {
                ++maxCount;
            }
        }

        return Math.max((maxExec - 1) * (n + 1) + maxCount, tasks.length);
    }
}

 

例题5:最长有效括号

题解1:动态规划算法

大佬题解添加链接描述
时间复杂度: O(n)
空间复杂度: O(n)

class Solution {
    public int longestValidParentheses(String s) {
        int[] dp=new int[s.length()];
        int result=0;
        for(int i=1;i<s.length();++i){
            if(s.charAt(i)==')'){
                if(s.charAt(i-1)=='('){
                    dp[i]=2;
                    if(i-2>=0){
                        dp[i]=dp[i-2]+dp[i];
                    }
                }else if(dp[i-1]>0){
                    if(i-dp[i-1]-1>=0&&s.charAt(i-dp[i-1]-1)=='('){
                        dp[i]=dp[i-1]+2;
                        if(i-dp[i-1]-2>=0){
                            dp[i]=dp[i-dp[i-1]-2]+dp[i];
                        }
                    }
                }
            }
            if(dp[i]>result){
                result=dp[i];
            }
        }
        return result;
    }
}
        

题解2:栈算法

时间复杂度: O(n)
空间复杂度: O(n)

class Solution {
    public int longestValidParentheses(String s) {
        Stack<Integer> stack=new Stack<>(); 
        stack.push(-1);
        int result=0;
        for(int i=0;i<s.length();++i){
            if(s.charAt(i)=='('){
                stack.push(i);
            }else{
                stack.pop();
                if(stack.isEmpty()){
                    stack.push(i);
                }else{
                    result=Math.max(result,i-stack.peek());
                }
            }
        }
        return result;
    }
}
        

题解3:贪心算法

时间复杂度: O(n)
空间复杂度: O(1)

class Solution {
    public int longestValidParentheses(String s) {
        int leftB=0,rightB=0;
        int maxLength=0;
        for(int i=0;i<s.length();++i){
            if(s.charAt(i)=='('){
                ++leftB;
            }else{
                ++rightB;
            }
            if(leftB==rightB){
                maxLength=Math.max(maxLength,2*rightB);
            }else if(leftB<rightB){
                leftB=0;
                rightB=0;
            }
        }
        leftB=0;
        rightB=0;
        for(int i=s.length()-1;i>=0;--i){
            if(s.charAt(i)=='('){
                ++leftB;
            }else{
                ++rightB;
            }
            if(leftB==rightB){
                maxLength=Math.max(maxLength,2*leftB);
            }else if(leftB>rightB){
                leftB=0;
                rightB=0;
            }
        }        
        return maxLength;
    }
}

 

例题6:跳跃游戏

class Solution {
    public boolean canJump(int[] nums) {
        int n=nums.length;
        int maxD=0;
        for(int i=0;i<n;++i){
            if(maxD<i){
                return false;
            }
            maxD=Math.max(maxD,i+nums[i]);
            if(maxD>=n-1){
                return true;
            }
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值