左神高阶提升班5(贪心尝试、范围上的尝试模型

news2025/1/11 14:08:49

目录

【案例1 贪心尝试】

【题目描述】

【思路解析】

【代码实现】

【案例2  范围上的尝试模型】

【题目描述】

【思路解析】

【代码实现】

【案例3  范围上的尝试模型】

【题目描述】

【思路解析】

【代码实现】

【案例4  从左至右上尝试的模型 + 范围上的尝试模型】

【题目描述】

【思路解析】

【代码实现】

【案例5 范围上的尝试模型】

【题目描述】 

【思路解析】

【代码实现】


大家觉得写得可以的话,可以加入QQ群907575059一起讨论算法知识.

 

【案例1 贪心尝试】

【题目描述】

【思路解析】

先将整个数组排序,如果最后一个位置的值大于limit返回Integer.MAX_VALUE,表示不可能过岸。

arr[arr.length - 1] <= limit / 2如果满足这个条件,任意两个人都可以配对上一个船
arr[0] > limit / 2 如果满足这个条件,只能一个人上一个穿

否则找到小于等于limit/2最右的位置left,然后使用两个指针,p从left往0遍历,q从left+1往arr.lenth遍历。

(1)如果 p + q <= limit,此时q++ (这里q++时,统计q遍历的长度),直到p+q>limit。此时p左边的对应长度全部满足对应的p + q < limit。如果p左边长度不足,就将所有p的用来解决q。

(2)如果p+q > limit,p--。

遍历完成后,右边剩下的每个人单独安排一个船,左边剩下的安排(leftNum + 1)/2;解决多少个q就安排多少个船。

【代码实现】

package AdvancedPromotion5;

import java.util.Arrays;

/**
 * @ProjectName: study3
 * @FileName: Ex1
 * @author:HWJ
 * @Data: 2023/9/24 16:18
 */
public class Ex1 {
    public static void main(String[] args) {
        int[] arr = {1,2,2,3,4,4,5,5,5,6,6,6,6,7,7,7,8,8,8,9,9,9,11,10,11,12};
        System.out.println(need(arr, 13));
    }

    public static int need(int[] arr, int limit) {
        Arrays.sort(arr);
        if (arr[arr.length - 1] > limit) {
            return Integer.MAX_VALUE;
        }

        if (arr[arr.length - 1] <= limit / 2) { // 如果满足这个条件,任意两个人都可以配对上一个船
            return (arr.length + 1) / 2;
        }
        if (arr[0] > limit / 2) {  // 如果满足这个条件,只能一个人上一个穿
            return arr.length;
        }

        int left = -1;
        for (int i = arr.length - 1; i >= 0; i--) {
            if (arr[i] <= limit / 2) {
                left = i;
                break;
            }
        }

        int p = left;
        int q = left + 1;
        int unSolved = 0;
        while (p >= 0) {
            int solve = 0;
            while (q < arr.length && arr[p] + arr[q] <= limit) {
                solve++;
                q++;
            }
            if (solve > 0) {
                p = Math.max(p - solve, -1); // 如果能解决完,就全部解决
                // 不能就直接赋值-1,退出循环。
            } else {
                unSolved++;
                p--;
                // 我们只用记录左边没有解决的数量,就可以通过左边总数得到左边已经解决的数量
                // 左边解决的数量,又等于右边解决的数量,通过这个又可以得到右边没有解决的数量。这样就得到了我们所需要的所有信息
            }
        }
        int leftNum = left + 1;
        int right = arr.length - leftNum;
        return right + (unSolved + 1) / 2;
    }
}

【案例2  范围上的尝试模型】

【题目描述】

【思路解析】

求公共子序列的做法看 案例6左神高阶进阶班4 (尼姆博弈问题、k伪进制、递归到动态规划、优先级结合的递归套路、子串的递归套路,子序列的递归套路,动态规划的压缩技巧)_Studying~的博客-CSDN博客

第一种做法,字符串str和它的逆序unStr求最长公共子序列则是他们的最长回文子序列。

第二种做法,给出一个定义dp[i][j]表示str【i 。。。j】上的最长回文子序列长度。

则最长回文子序列可能性包括:

(1)包含i位置,包含j位置,只有str[i] == str[j]

(2)包含i位置,不包含j位置

(3)不包含i位置,包含j位置

(4)不包含i位置,不包含j位置。

【代码实现】

package AdvancedPromotion5;


/**
 * @ProjectName: study3
 * @FileName: Ex2
 * @author:HWJ
 * @Data: 2023/9/24 16:59
 */
public class Ex2 {
    public static void main(String[] args) {
        String str = "123akmk321";
        System.out.println(getMax(str));
    }

    public static int getMax(String s){
        char[] str = s.toCharArray();
        int[][] map = new int[str.length][str.length];

        for (int i = 0; i < str.length; i++) { // 填充i == j 和 j == i + 1的情况,这个是很好的判断,不用考虑可能性
            map[i][i] = 1;
            if (i < str.length - 1){
                map[i][i + 1] = str[i] ==  str[i + 1] ? 2 : 1;
            }
        }
        for (int i = str.length - 3; i >= 0; i--) {
            for (int j = i + 2; j < str.length; j++) {
                int p1 = map[i][j - 1];
                int p2 = map[i + 1][j];
                int p3 = map[i + 1][j - 1] + (str[i] == str[j] ? 2 : 0);
                map[i][j] = Math.max(p1, Math.max(p2, p3));
            }
        }
        return map[0][str.length - 1];
    }
}

【案例3  范围上的尝试模型】

【题目描述】

【思路解析】

构造结果dp[i][j]表示把str[i.....j]变为回文串至少需要多少添加字符。

(1)str[i] != str[j],此时分为两种策略,先搞定str[i......j-1]让其变为回文串,然后再将次回文串的左侧填加一个str[j]则整体是一个回文串。或者先搞定str[i +1......j]让其变为回文串,然后再将次回文串的右侧填加一个str[i]则整体是一个回文串。

(2)str[i] == str[j],此时只用将str[i+1 ...... j-1]变为回文串,整体就是回文串。

最后三种可能性求最小值,则得到我们需要的答案。通过动态规划填完表后,我们通过表逆推得到返回的答案。

【代码实现】

package AdvancedPromotion5;

/**
 * @ProjectName: study3
 * @FileName: Ex3
 * @author:HWJ
 * @Data: 2023/9/24 17:10
 */
public class Ex3 {
    public static void main(String[] args) {
        String s = "123afga1321";
        System.out.println(record(s));
    }

    public static String record(String s) {
        int[][] map = recordMap(s);
        String ans = recordStr(map, s.toCharArray());
        return ans;
    }

    public static int[][] recordMap(String s) {
        char[] str = s.toCharArray();
        int len = str.length;
        int[][] map = new int[len][len];
        for (int i = 0; i < len; i++) {
            map[i][i] = 0;
            if (i < len - 1) {
                map[i][i + 1] = (str[i] == str[i + 1] ? 0 : 1);
            }
        }
        for (int i = len - 3; i >= 0; i--) {
            for (int j = i + 2; j < len; j++) {
                int p1 = map[i + 1][j] + 1;
                int p2 = map[i][j - 1] + 1;
                map[i][j] = Math.min(p1, p2);
                if (str[i] == str[j]) {
                    map[i][j] = Math.min(map[i][j], map[i + 1][j - 1]);
                }
            }
        }
        return map;
    }

    public static String recordStr(int[][] map, char[] str) {
        int len = map.length;
        int need = map[0][len - 1];
        int p = 0;
        int q = len - 1;
        char[] ans = new char[len + need];
        int i = 0;
        int j = ans.length - 1;
        while (p <= q) {
            if (p == q) {
                ans[i] = str[p];
                break;
            }
            if (str[p] == str[q]) {
                int p1 = map[p + 1][q - 1];
                int p2 = map[p + 1][q];
                if (map[p][q] == p1) {
                    ans[i++] = str[p++];
                    ans[j--] = str[q--];
                } else if (map[p][q] == p2 + 1) {
                    ans[i++] = str[p];
                    ans[j--] = str[p++];
                } else {
                    ans[i++] = str[q];
                    ans[j--] = str[q--];
                }
            } else {
                int p1 = map[p + 1][q];
                if (map[p][q] == p1 + 1) {
                    ans[i++] = str[p];
                    ans[j--] = str[p++];
                } else {
                    ans[i++] = str[q];
                    ans[j--] = str[q--];
                }
            }
        }
        return String.valueOf(ans);
    }
}

【案例4  从左至右上尝试的模型 + 范围上的尝试模型】

【题目描述】

【思路解析】

因为我们要将其全部切成回文子串的最小切割数,则可以从左至右遍历每种可能性,遍历可能性时判断当前切割是否合理,如果当前切割保证当前切下来的是合理回文子串,即继续往下切。这种遍历下时间复杂度O(N^2),又因为每次遍历都要进行一次判断过程,判断时间复杂度O(N),所以总体时间复杂度为O(N^3)。这时时间复杂度过高,我们需要通过范围上的模型来对判断过程加速。

统计一个表,map[i][j]表示str[i....j]是不是回文子串,回文子串一定要满足str[i] == str[j],并且str[i + 1][j - 1]也是回文子串。

【代码实现】

package AdvancedPromotion5;

/**
 * @ProjectName: study3
 * @FileName: Ex4
 * @author:HWJ
 * @Data: 2023/9/25 8:32
 */
public class Ex4 {
    public static void main(String[] args) {
        String str = "ABA";
        boolean[][] map = judge(str);
        System.out.println(getMin(str.toCharArray(), 0, map));
    }

    public static int getMin(char[] str, int index, boolean[][] map){
        if (index == str.length){
            return -1;
        }
        int res = Integer.MAX_VALUE;
        for (int i = index; i < str.length; i++) {
            if (map[index][i]){
                res = Math.min(res, 1 + getMin(str, i + 1, map));
            }
        }
        return res;

    }

    public static boolean[][] judge(String s){
        boolean[][] map = new boolean[s.length()][s.length()];
        char[] str = s.toCharArray();
        for (int k = 0; k < str.length; k++) {
            map[k][k] = true;
            if (k < str.length - 1){
                map[k][k + 1] = str[k] == str[k + 1];
            }
        }
        for (int k = str.length - 3; k >= 0 ; k--) {
            for (int l = k + 2; l < str.length; l++) {
                if (str[k] == str[l]){
                    map[k][l] = map[k + 1][l - 1];
                }else {
                    map[k][l] = false;
                }
            }
        }
        return map;
    }
}

【案例5 范围上的尝试模型】

【题目描述】 

【思路解析】

构造一个二维表,map[i][j]表示str[i .....j]有多少个回文子序列。

则回文子序列分为以下可能性:

(1)包含i位置,包含j位置。

(2)包含i位置,不包含j位置。

(3)不包含i位置,包含j位置。

(4)不包含i位置,不包含j位置。

map[i + 1][j] 表示不包含i位置的所有回文子序列个数,可能包含j位置,也可能不包含j位置,代表(3)(4)可能性。j

map[i][j - 1] 表示不包含j位置的所有回文子序列个数,可能包含i位置,也可能不包含i位置,代表(2)(4)可能性。

map[i+1][j-1]表示不包含j位置并且不包含j位置的所有回文子序列个数,代表(4)可能性。

(1)可能性只有在str[i] == str[j]时才有这个可能性,数值等于map[i+1][j-1] + 1.因为如果如果除去这两个是回文数,加上任然是回文数,并且多一个只有这两个序列的情况。

【代码实现】

package AdvancedPromotion5;

/**
 * @ProjectName: study3
 * @FileName: Ex5
 * @author:HWJ
 * @Data: 2023/9/25 9:05
 */
public class Ex5 {
    public static void main(String[] args) {
        String str= "ABA";
        System.out.println(getNum(str));
    }

    public static int getNum(String s){
        char[] str = s.toCharArray();
        int len = str.length;
        int[][] map = new int[len][len];
        for (int i = 0; i < len; i++) {
            map[i][i] = 1;
            if (i < len - 1){
                map[i][i + 1] = (str[i] == str[i + 1] ? 3 : 2);
            }
        }
        for (int i = len - 3; i >= 0; i--) {
            for (int j = i + 2; j < len; j++) {
                map[i][j] = map[i + 1][j] + map[i][j - 1] - map[i + 1][j - 1];
                if (str[i] == str[j]){
                    map[i][j] += (map[i + 1][j - 1] + 1);
                }
            }
        }
        return map[0][len - 1];
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1039507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ATTCK红队评估实战靶场二

描述 红队实战系列&#xff0c;主要以真实企业环境为实例搭建一系列靶场&#xff0c;通过练习、视频教程、博客三位一体学习。本次红队环境主要Access Token利用、WMI利用、域漏洞利用SMB relay&#xff0c;EWS relay&#xff0c;PTT(PTC)&#xff0c;MS14-068&#xff0c;GPP…

Spring学习笔记10 JdbcTemplate

Spring学习笔记9 SpringIOC注解式开发_biubiubiu0706的博客-CSDN博客 JdbcTemplate是Spring提供的一个JDBC模板类,是对JDBC的封装,简化JDBC代码. 新建模块spring-jdbctemplate 引入依赖 <dependencies><!--Spring Context依赖--><dependency><groupId>…

直播软件App开发:10个关键步骤,从零到一掌握

欢迎来到本文&#xff0c;我将为您解析直播软件App开发的关键步骤&#xff0c;帮助您从零开始掌握这一领域。作为该主题领域的专家&#xff0c;我将为您分享十个重要的步骤&#xff0c;带您实现直播软件App的开发目标。 步骤一&#xff1a;市场调研与需求分析 在直播软件App开…

购物新时尚RFID自助结账

购物已经变得更加简单和方便了&#xff0c;归功于RFID自助结账。别再排队等收银员了&#xff0c;让我们来看看这个酷炫的新方式。 RFID是什么&#xff1f;RFID就是那些小电子标签&#xff0c;它们能够让物品自动被识别。每个商品都有一个这样的标签&#xff0c;而RFID读卡器就…

Ansys Zemax | 如何设计光谱仪——实际应用

光谱学是一种无创性技术&#xff0c;是研究组织、等离子体和材料的最强大工具之一。 本文介绍了如何使用市售的光学元件来实现透镜-光栅-透镜&#xff08;LGL&#xff09;光谱仪。进行光谱仪的设置&#xff0c;并对其设计进行改进和优化。&#xff08;联系我们获取文章附件&…

品牌新闻稿大纲怎么写?建议收藏

一篇品牌新闻稿的大纲就犹如是全篇的骨架&#xff0c;骨架搭建好&#xff0c;然后再慢慢填充新鲜血液。品牌新闻稿的大纲亦是全文的写作方向&#xff0c;写好新闻稿大纲才能进行下一步撰写&#xff0c;写好新闻稿大纲你的稿件就离成功不远了。品牌新闻稿大纲怎么写&#xff1f;…

Tomcat中文路径目录

一、问题描述 linux环境下tomcat发布了包含中文名字的页面和文件&#xff0c;浏览器访问报404&#xff0c;非中文页面没有问题&#xff1b;本人为RP设计的原型图发布&#xff0c;其中包含了大量的中文文件和路径 二、解决步骤 第一步&#xff0c;设置tomcat&#xff0c;配置…

数据结构——快排与归并

排序算法 前言一、快速排序hoare版本挖坑法前后指针版本快速排序优化&#xff1a;快速排序非递归快速排序的特性总结&#xff1a; 二、归并排序基本思想&#xff1a;归并排序的特性总结&#xff1a; 总结 前言 重要的事说三遍&#xff01; 学习&#xff01;学习&#xff01;学…

能把西瓜塞进口袋吗?详解Java数据类型与变量

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、数据类型二、变量1、整型变量Ⅰ、整型变量的初始化Ⅱ、长整型变量Ⅲ、短整型变量 2、字节型变量3、浮点型变量Ⅰ、双精度浮…

支撑位和阻力位在Renko和烛台图如何使用?FPmarkets澳福3秒回答

很多投资者都知道&#xff0c;Renko图表和普通日本烛台都会采用相同的交易信号&#xff0c;即支撑位和阻力位。那么支撑位和阻力位在Renko和烛台图如何使用?FPmarkets澳福3秒回答。 这些信号在任何时间框架上都会出现&#xff0c;且在蜡烛图交易中颇受欢迎。对于Renko图表而言…

串口数据太多,接收不完。Arduino修改串口缓冲区大小的办法

和网上搜到修改的方法不太一样&#xff0c;可能是版本不一样&#xff0c;我的方法供大家参考。arduino的串口缓冲区_Arduino修改串口缓冲区大小的办法 找到Serial.begin(115200);的定义&#xff0c; 串口收发代码示例 #include <Arduino.h> void setup() {// initial…

二叉树题目:翻转等价二叉树

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;翻转等价二叉树 出处&#xff1a;951. 翻转等价二叉树 难度 4 级 题目描述 要求 对于二叉树&#xff0c;我们可以定义如下翻转操作&#xff1a;选…

【app篇】写个简单的BLE调试app,练练手,同时为后续调试ESP32 BLE做个支持

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-09-25 ❤️❤️ 本篇更新记录 2023-09-25 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

5、Nacos服务注册服务端源码分析(四)之NotifyCenter

上篇我们讲server端处理服务注册源码时&#xff0c;遇到了一个关键类NotifyCenter&#xff0c;本篇就主要来分析下这个类。 NotifyCenter 这个类所在包&#xff1a;nacos-common /*** Unified Event Notify Center.*/通过类注释可以看出来这个类是一个统一的事件通知中心&am…

PHP8中的构造方法和析构方法-PHP8知识详解

今日分享的内容是php8中的构造方法和析构方法&#xff0c;我们把构造方法和析构方法这两个方法分开来讲&#xff1a; 1、构造方法 构造方法存在于每个声明的类中&#xff0c;主要作用是执行一些初始化任务。如果类中没有直接声明构造方法&#xff0c;那么类会默认地生成一个没…

仿网吧游戏菜单-超好用

GG软件菜单(X64)仿网吧菜单: https://url75.ctfile.com/f/1834175-943877085-2d844a?p6775 (访问密码: 6775)

如何将前后端分离的项目部署在服务器上

宝塔Linux部署&#xff1a; 因为要部署前端我们先下个nigx Tomcat,下载这个只是为了java&#xff0c;它里面包含java的 前端 在去添加站点&#xff0c;域名暂时是自己的公网 然后打开新建的站点&#xff0c;把里面的文件全删掉&#xff0c;再把自己的前端dist里的文件全选拖…

高速USB转8路RS422串口

基于480Mbps 高速USB转8路串口芯片CH348&#xff0c;可以为各类主机扩展出8个独立的串口。使用厂商提供的VCP串口驱动程序&#xff0c;可支持Windows、Linux、Android、macOS等操作系统。使用单个CH348芯片即可实现USB一拖八串口转接产品&#xff0c;高速USB收发器和控制器、高…

SpringCloud 简单的了解

什么是SpringCloud ? 基于 Spring Boot 的 Spring 集成应用程序&#xff0c;它利用 Spring Boot 的开发便利性简化了分布式系统的开发&#xff0c;提供与外部系统的集成。 如服务注册与发现、配置中心、负载均衡、断路器、消息总线、数据监控等&#xff1b;换句话说&#xff…

拼多多商品详情数据接口

拼多多商品详情接口的具体内容。获取拼多多商品详情&#xff0c;可以参考如下方式&#xff1a; item_get_app-根据ID取商品详情原数据接口包括&#xff1a;标题&#xff0c;价格&#xff0c;促销价&#xff0c;优惠券&#xff0c;库存&#xff0c;销量&#xff0c;详情图片&am…