贪心算法:
例题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;
}
}