当前位置: 首页 > news >正文

贪心+二分

删数问题

题目描述

键盘输入一个高精度的正整数 N N N(不超过 250 250 250 位),去掉其中任意 k k k 个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的 N N N k k k,寻找一种方案使得剩下的数字组成的新数最小。

输入格式

输入两行正整数。

第一行输入一个高精度的正整数 n n n

第二行输入一个正整数 k k k,表示需要删除的数字个数。

输出格式

输出一个整数,最后剩下的最小数。

样例 #1

样例输入 #1

175438 
4

样例输出 #1

13

题解:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
string s; int k; vector<char> st;

int main()
{
    cin >> s >> k;
    if (s.size() <= k) {
        cout << 0;
        return 0;
    }
    for (int i = 0; i < s.size(); i++) {
        if (st.empty() || (st[st.size() - 1] <= s[i]) && (st.size() < s.size() - k)) {
            st.push_back(s[i]);
        }
        else if (s[i] < st[st.size() - 1]) {
            int l = 0, r = st.size() - 1, mid;
            while (l < r) {
                mid = (l + r) / 2;
                if (st[mid] > s[i])
                    r = mid;
                else
                    l = mid + 1;
            }
            if (s.size() - k - r <= s.size() - i) {
                while (st.size() >= r + 1)
                    st.pop_back();
                st.push_back(s[i]);
            }
            else {
                while (s.size() - k - st.size() <= s.size() - i - 1)
                    st.pop_back();
                st.push_back(s[i]);
            }
        }
    }
    bool flag = 0;
    for (int i = 0; i < st.size(); i++) {
        if (st[i] != '0') {
            flag = true;
        }
        if (flag) {
            cout << st[i];
        }
    }
    if (!flag)
        cout << 0;
    return 0;
}

思路:

  • 定义一个栈用于存储最后会留下的数。

  • 根据贪心的思想,位数相同的两个数作比较,只要高位数字越小整个数字就越小,举例199和300.

  • 遍历整个字符串,于是对于每个数字可分为可以直接入栈的情况和需要考虑后决定是否入栈的情况:

    • 直接入栈的情况:当栈空或者栈顶数字小于等于扫描到的数字,并且栈里数字的个数不能大于原数删除k个数后剩下的数字的个数。
    • 需要考虑的情况:
      栈顶数字大于扫描到的数字,换而言之,如果我用这个数字替代栈顶,所得的数字可能是更优的。
      比如栈里现在的数字是198,扫描到的数字是3,那么这个时候,我用3替换8,可以得到193,甚至可以更往前,得到13.
    • 那么要如何考虑呢?
      首先,根据可以直接入栈的情况,可以很容易得到栈里的数字一定是非递减的。其次当我们找到一个比栈顶小的数字时,我们还应该看看能不能继续往前,找到更适合的位置,比如刚刚举例的198和3.
      那么这个查找的过程,我们就可以用二分,用刚刚198和3的例子,找到第一个比3大的数,套二分查找左边界的板子,直接用upper_bound()也行。
      找到这个边界之后,就把所有大于等于这个边界的数字全部出栈,在把3入栈,得到13
      这个时候还会出现一个问题就是,万一字符串继续往后扫描剩下的数不够了怎么办,这个时候字符串后面剩下几个数字就出栈几个数字,比如3是字符串的倒数第1个数字,那么只能变成193.
  • 做完这一切之后,得到的字符串可能以0开头,也可能被删光了,所以要做一些特殊处理,dddd

相关文章:

  • Geoserver Windows 安装部署教程
  • haproxy,nginx,keepalived综合运用
  • 动态多目标优化算法:MOEA/D-FD求解FDA1、FDA2、FDA3、FDA4和FDA5(Matlab代码)
  • 【基于C的排序算法】插入排序之直接插入排序
  • Golang——从入门到放弃
  • 报告分享|数据变现,车企利润新增长点
  • 计算机网络基本概念
  • 零基础入门MATLAB(一篇十分钟)
  • 求最大公约数、最小公倍数、
  • 15、IOC 之ApplicationContext 的附加功能
  • Hive sql 行列转换(行转列,列转行)
  • 【MATLAB教程案例10】使用MATLAB自带的LDPC工具箱实现LDPC编译码误码率仿真
  • 小学数学学习:神奇的走马灯数 142857
  • 【OFDM系列6】MIMO-OFDM系统模型、迫零(ZF)均衡检测和最小均方误差(MMSE)均衡检测原理和公式推导
  • 点云处理简介
  • 【comparator, comparable】小总结
  • Apache Pulsar 2.1 重磅发布
  • eclipse的离线汉化
  • If…else
  • IndexedDB
  • java8 Stream Pipelines 浅析
  • JavaScript DOM 10 - 滚动
  • Java多态
  • java多线程
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • magento 货币换算
  • PAT A1092
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • php的插入排序,通过双层for循环
  • VuePress 静态网站生成
  • vue数据传递--我有特殊的实现技巧
  • Vue小说阅读器(仿追书神器)
  • Vultr 教程目录
  • webpack入门学习手记(二)
  • 高性能JavaScript阅读简记(三)
  • 机器学习学习笔记一
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 前端自动化解决方案
  • 前嗅ForeSpider教程:创建模板
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 问题之ssh中Host key verification failed的解决
  • 用Python写一份独特的元宵节祝福
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .NET 8.0 中有哪些新的变化?
  • .net与java建立WebService再互相调用