dp表,哈希表,力扣5.最长回文子串力扣1745.分割回文串IV力扣132.分割回文串II优先级队列(堆)是什么下面是手动实现小根堆力扣1046.最后一块石头的重量

目录

力扣5.最长回文子串

力扣1745.分割回文串IV

力扣132.分割回文串II

优先级队列(堆)是什么

下面是手动实现小根堆

力扣1046.最后一块石头的重量


力扣5.最长回文子串

使用dp[i][j]:以i位置开头,以j位置结尾。

class Solution {
       public static String longestPalindrome(String s) {
        int n=s.length();
        //dp[i][j]:设置以i位置开头,j位置结尾的dp
        int len=1;
        int begin=0;
    boolean[][]dp=new boolean[n][n];
    for(int i=n-1;i>=0;i--){
      for(int j=i;j<n;j++){
          if(s.charAt(i)==s.charAt(j)){
              if(i==j||i+1==j){
                  dp[i][j]=true;
              }
              else{
                  //中间有字符,接下来看看i+1和j-1这个位置看看
                      dp[i][j]=dp[i+1][j-1];
                  }
              }
          if(dp[i][j]==true&&j-i+1>len){
              len=j-i+1;
              begin=i;
          }
      }
    }
     return s.substring(begin,begin+len);
    }
}

力扣1745.分割回文串IV

简单的去判定是不是回文子串用dp已经很常见了,来分析一下比较罕见的分割成三段

class Solution {
    public boolean checkPartitioning(String s) {
    int n=s.length();
    boolean[][]dp=new boolean[n][n];
    for(int i=n-1;i>=0;i--){
        for(int j=i;j<n;j++){
      if(s.charAt(j)==s.charAt(i)){
        if(i+1==j||i==j){
            dp[i][j]=true;
        }
       else 
        dp[i][j]=dp[i+1][j-1];
       
      }
        }
    }
    for(int i=1;i<n-1;i++){
        for(int j=i;j<n-1;j++){
        if(dp[0][i-1]&&dp[i][j]&&dp[j+1][n-1])
        return true;
        }
    }

return false;
    }
}

力扣132.分割回文串II

1.dp[i]:s[0,i]区间上最长的子串,最少分割次数

(假如没有这个优化,则会造成越界,因为会有三次循环,判断0-i是否回文,i-j是不是回文,0-j是不是回文串)

2.初始化

dp表内所有的初始值都初始化为无限大

3.填表顺序:

从左往右填表

4.返回值

dp[n-1]

class Solution {
    public int minCut(String s) {
    int n=s.length();
    boolean[][]isreturn=new boolean[n][n];
    for(int i=n-1;i>=0;i--){
        for(int j=i;j<n;j++){
         if(s.charAt(i)==s.charAt(j)){
            if(i==j||i+1==j){
                isreturn[i][j]=true;
            }else{
                isreturn[i][j]=isreturn[i+1][j-1];
            }
         }
        }
    }
    int []dp=new int[n];
    for(int i=0;i<n;i++)dp[i]=Integer.MAX_VALUE;
    for(int i=0;i<n;i++){
        if(isreturn[0][i]==true) dp[i]=0;
        else{
            for(int j=1;j<=i;j++){
              //  1.dp[i]:s[0,i]区间上最长的子串,最少分割次数
                if(isreturn[j][i]==true)
                //初始化无穷大,防止其干扰min求值
                dp[i]=Math.min(dp[i],dp[j-1]+1);
            }
        }
    }
    return dp[n-1];
    }
}

优先级队列(堆)是什么

默认情况下,堆是小根堆

下面是手动实现小根堆

使用数组和一个计数结构

import java.util.Arrays;

public class TestHeap {
    //自己去写一个堆
    public int[] elem;

    public int usedSize;

    public TestHeap() {
        this.elem = new int[10];
    }

    //创建一个大根堆
    public void createHeap(int[] array) {
        for (int i = 0; i < array.length; i++) {
            elem[i] = array[i];
            usedSize++;
        }
//parent=child-1/2
        for (int parent = (usedSize - 1 - 1) / 2; parent >= 0; parent--) {
            //向下调整,需要给的数字,当前父亲位置,结束位置
            shiftDown(parent, usedSize);
        }
    }



    /**
     * @param parent 每颗子树根节点
     * @param len    每个子树的结束位置
     */
    //向下调整,已知孩子下标len-1拿到,父亲节点(len-1-1)/2
    public void shiftDown(int parent, int len) {
        int child = parent * 2 + 1;
        //看他是否有左孩子
//查看左右孩子哪个大,和大的交换,因为要变成大根堆
        while (child < len) {
            if(child+1<len){
            if(elem[child]<elem[child+1]){
                child=child+1;
            }
            }
            if (elem[child] > elem[parent]) {
                int tmp = elem[parent];
                elem[parent] =elem[ child];
                elem[child] = tmp;
                parent = child;
                child = parent * 2 + 1;
            }else{
                break;
            }
        }
    }


    //保证仍然原先是大根堆,还是小根堆(当插入一个元素的时候,先插入到最后一个位置),插入后,直接和根比较
    //向上调整
    public void push(int val){
        //检查是否满了
        //2.存数据
        if(isFull()){
            elem=Arrays.copyOf(elem,2*elem.length);
        }
        elem[usedSize]=val;
        usedSize++;

        shiftUp(usedSize-1);
    }



    public  boolean isFull(){
        return usedSize==elem.length;
    }



    public void shiftUp(int child){
        int parent=(child-1)*2;
        while(child>0){
            if(elem[child]>elem[parent]){
                int tmp=elem[child];
                elem[child]=elem[parent];
                elem[parent]=tmp;
                child=parent;
                parent=(child-1)/2;
            }else{
                break;
            }
        }
    }
    //假如只能删除堆顶,还要保持他是一个大根堆的形态(那么就要头和最下面的换,然后去,向下调整)
public void  poll(){
        int tmp =elem[0];
        elem[0]=elem[usedSize-1];
        //让0下标元素和最下面的元素交换,然后再去向下调整(把size--即可)
        elem[usedSize-1]=tmp;
        usedSize--;
        shiftDown(0,usedSize);

}
//堆排序
    public void headSort(){
        int end=usedSize-1;
        while(end>0){
            //本身已经是一个大根堆
            int tmp=elem[0];
            elem[0]=elem[end];
            elem[end]=tmp;
            shiftDown(0,end);
            end--;
        }
    }



}

力扣1046.最后一块石头的重量

class Solution {
      public static int lastStoneWeight(int[] stones) {
        //创建一个大根堆
    PriorityQueue<Integer>heap=new PriorityQueue<>((a,b)->b-a);
       //2.把所有的石头放进堆里面
        for(int x:stones){
            heap.offer(x);
        }
        //3.模拟
        while(heap.size()>1){
            int a=heap.poll();
            int b=heap.poll();
            //先a再b,然后再大于等于
            if(a>b){
                heap.offer(a-b);
            }
        }
        //拿出堆顶元素
          return  heap.isEmpty()?0: heap.peek();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗哥不是甜妹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值