首页 > 试题广场 >

最大新整数

[编程题]最大新整数
  • 热度指数:2768 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
有一十进制正整数,移除其中的 K 个数,使剩下的数字是所有可能中最大的。
假设:
字符串的长度一定大于等于 K
字符串不会以 0 开头

输入描述:
一行由正整数组成的数字字符串,和一个正整数 K,两个数据用空格隔开,如:1432219 3。
字符串长度不超过2000,K<=2000。


输出描述:
移除 K 位后可能的最大的数字字符串。
如 1432219 移除 1, 2, 1 这 3 个数字后得到 4329,为所有可能中的最大值。
示例1

输入

1432219 3

输出

4329
我来一个python最优的解法:
1. 用一个栈记录符合条件的数字,只要当前循环下的数字比栈末尾的数字大,我们就从后向前删除栈内的数字,并更新K的的值,记做k。直至k==0 或者 数字不大于栈末尾的数字为止。
2 如果循环之后,K还有剩余k,那么删除栈内后k个数字即可。
if __name__ == "__main__":
    s, K = raw_input().strip().split()
    s = list(s)
    k = int(K)
    ans = [s[0]]
    for i in s[1:]:
        while ans and k>0:
            if i>ans[-1]:
                ans.pop()
                k -= 1
            else:
                break
        ans.append(i)
    if k>0:
        ans = ans[:-k]
    print(''.join(ans))


发表于 2019-08-22 19:16:23 回复(1)
/*依次扫描,如果当前数比后一位小,那么移除,可使当前数最大,重复此流程k次
如果一直没有数比后一位小那就移除结尾*/
int main(){
    string str;
    cin>>str;
    int k,max=0,temp;
    cin>>k;
    for(int i=0;i<k;i++)    
    {
		for(int j=0;j<str.length();j++)
		if(str[j]<str[j+1]){
		str.erase(str.begin()+j);
		break;	
		}
        else if(j==str.length()-1)
        str.erase(str.begin()+j);
	}
	 for(int i=0;i<str.length();i++)
    {
		cout<<str[i];
	}
    return 0; 
}

发表于 2019-12-26 15:23:40 回复(1)
 """"
找到[0,K]区间内最大值对应的第一个下标 idx,
移除idx之前的所有数字,更新K = K-idx,保留idx对应的数字,对idx之后的数字串重复上一步骤
例如:输入 41681991713273619813 10 输出 9977619813
对s[0:10] 求最大值对应下标 idx=5,
移除s[0:5),K=10-5=5 ,输出s[idx]即9,对s[6:end)重复操作
对s[6:6+5] 求 idx=0,移除s[6:6+idx)即此次不移除,输出s[6+idx]即9,对s[7:end)重复操作
对s[7:7+5] 求 idx=1,移除s[7:7+idx),K=5-1=4,输出s[7+idx]即s[8]=7,对s[9:end)重复操作
对s[9:9+4] 求 idx=3,移除s[7:7+idx),K=4-3=1,输出s[9+idx]即s[12]=7,对s[13:end)重复操作
对s[13:13+1] 求 idx=1,移除s[13:13+idx),K=1-1=0,输出s[13+idx]即s[14]=6,输出s[15:end)
"""

if __name__ == "__main__":
    s, K = input().strip().split()
    s = list(s)
    K = int(K)
    t = 0
    ans = []
    while K:
        if K == len(s) - t:
            t = len(s)
            break
        idx = s[t:t + K + 1].index(max(s[t:t + K + 1]))
        ans.append(s[t + idx])
        K -= idx
        t += idx + 1
    ans += s[t:]
    print(''.join(ans))

发表于 2019-07-15 20:12:45 回复(0)
整体思路:首先从前往后遍历K次,将大数字尽量往前提,然后截取前面len(num)-k位数字即可。
	
#输入
(num,k) =input().split(' ')
#将字符串拆散为数组
num =list(str(num))
#要删除的位数
k =int(k)
#removed用于记录已经删除的位数
removed =0
#循环k次:
for j in range(k):
----#不断从前往后扫描(注意break):
----for i inrange(len(num)-1):
----#如果i位小于i+1位,删除此位数,使得大数字往前提。
--------if num[i]<num[i+1]:
--------del num[i]
--------removed +=1
--------break
#截取前面几位数字,使得数字的个数符合删除后的数量。
num =num[:len(num)-(k-removed)]
#从前往后乘10的倍数,输出。
rtn =0
for i inrange(len(num)):
----rtn =rtn+int(num[i])*(10**((len(num)-i-1)))
print(rtn)

编辑于 2019-03-21 21:52:15 回复(0)
//和上面的ElonB的思路大致是一样的
//用c++实现
#include<iostream>
(720)#include<vector>
#include<string>
using namespace std;
int main()
{
	string s;
	cin >> s;
	int k;
	cin >> k;
	int index = 0;
	int n;
	vector<char> t;
	int l;
	int max;
	for (int i = 1; i < s.size() && k; i++)
	{
		n = index;
		l = index;
		max = 0;
		for (int j = 0; j <= k && l < s.size(); j++,l++)
		{
			if (s[l] > max)
			{
				index = l;
				max = s[l];
			}
		}
		t.push_back(s[index]);
		k = k - (index - n);
        i=index;
		index++;
	}
	if (k == 0)
	{
		for (auto it : t)
			cout << it;
		cout << s.substr(index);
	}
	else
	{
		for (auto it = t.crbegin(); it != t.crend() - 1;)
		{
			if (k == 0)
				break;
			if (*it <= *(it + 1))
			{
				it=vector<char>::reverse_iterator(t.erase((++it).base()));
				k--;
			}
			else
				it++;
		}
		for (auto it : t)
			cout << it;
	}
}

发表于 2020-03-28 12:46:04 回复(0)
import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String s=sc.next();
        int k= sc.nextInt();
        Stack<Character>stack=new Stack();
        int n=s.length();
        for(int i=0;i<n;i++){
            while(!stack.empty() && stack.peek()<s.charAt(i) && k>0){
                stack.pop();
                k--;
            }
            stack.push(s.charAt(i));
        }
        while(k>0){
            stack.pop();
            k--;
        }
        StringBuilder sb = new StringBuilder();
        while(!stack.empty()){
            sb.append(stack.peek());
            stack.pop();
        }
        System.out.println(sb.reverse());
    }
}

发表于 2020-03-24 16:57:49 回复(0)
#include <bits/stdc++.h>
using namespace std;

int main(){
    string s;
    int k;
    cin>>s>>k;
    int n = s.length();
    stack<char> S;
    for(int i=0;i<n;i++){
        while(!S.empty() && S.top()<s[i] && k>0){
            S.pop();
            k--;
        }
        S.push(s[i]);
    }
    string r;
    while(!S.empty()){
        if(k<=0)
            r += S.top();
        S.pop();
        k--;
    }
    reverse(r.begin(), r.end());
    cout<<r<<endl;
    return 0;
}

发表于 2019-12-13 09:38:26 回复(0)
import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] str = sc.nextLine().split(" ");

        int remove = Integer.parseInt(str[1]);

        char[] num = str[0].toCharArray();
        int n = str[0].length();
        int[][] dp = new int[n][n];  //num数组i~j范围内的最大值

        for (int i = 0; i < n; i++) {
            dp[i][i] = num[i] - '0';
        }

        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                dp[i][j] = Math.max(dp[i][j - 1], num[j] - '0');
            }
        }

        final int choose = n - remove;
        int choosed = 0;
        StringBuilder ans = new StringBuilder();
        int st = 0, ed = n - choose;
        while (choosed < choose) {
            int max = dp[st][ed];  //每次选取st~ed的最大值
            int t = 0;
            for (int i = st; i <= ed; i++) {
                if(num[i] - '0' == max) {  //找到st~ed内最大值的下标
                    t = i;
                    ans.append(num[i]);
                    choosed++;
                    break;
                }
            }
            //调整范围
            st = t + 1;  
            ed = n - (choose - choosed);
        }

        System.out.println(ans.toString());
    }
}

发表于 2019-09-12 11:15:15 回复(0)
#include <bits/stdc++.h>
using namespace std;
int main(void){
    string str;
    int k;
    deque<char> que;
    cin>>str>>k;
    que.push_back(str[0]);
    for(int i = 1; i < str.length(); ++i){
        while(!que.empty() && k){
            if(str[i] > que.back()){
                que.pop_back();
                --k;
            }else
                break;
        }
        que.push_back(str[i]);
    }
    while(k--)
        que.pop_back();
    while(!que.empty()){
        cout<<que.front();
        que.pop_front();
    }
    cout<<endl;
    return 0;
}
把前面别人的python代码改成c++版本的
发表于 2019-09-06 15:56:00 回复(0)
单调栈解法
void solve(const string& S, int K) {
	int N = S.size();
	stack<char> st;
	for (auto c : S) {
		while (!st.empty() && st.top() < c && K > 0) {
			st.pop();
			--K;
		}
		st.push(c);
	}
	string res;
	while (!st.empty()) {
		if (K <= 0) {
			res += st.top();
		}
		st.pop();
		--K;
	}
	reverse(res.begin(), res.end());
	cout << res << endl;
}

int main() {
	string S;
	int K;
	cin >> S >> K;
	solve(S, K);
    return 0;
}


发表于 2019-11-21 23:34:59 回复(0)
import java.util.*;
//单调栈,为方便输出,使用StringBuffer来存储字符
public class Main{
      public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String str = sc.next().trim();
        int k = sc.nextInt();
        StringBuffer sb = new StringBuffer(""+str.charAt(0));
  
        for(int i = 1;i<str.length();i++){            
            char x = sb.charAt(sb.length()-1);
            while(k>0&&sb.length()>0&&sb.charAt(sb.length()-1)<str.charAt(i)){
                sb.deleteCharAt(sb.length()-1);
                k--;
            }
            sb.append(str.charAt(i));    
        }
          if(k==0){
              System.out.println(sb.toString());
          }else{
              System.out.println(sb.substring(0,sb.length()-k));
          }
         
    } 
}


发表于 2020-07-17 22:11:52 回复(0)
#include <bits/stdc++.h>
using namespace std;

int main(){
long long n;
int k;
cin>>n>>k;
string s;
vector<int> number;
int i=0;
while(n)
{
number.push_back(n%10);
n=n/10;
i++;
}
//    cout<<"i="<<i<<endl;
/*    for(int i=0;i<number.size();i++)
{
cout<<number[i];
}*/
cout<<endl;
int j=0;
int count=4;
int zhongdian;
int z;
int weishu=i-k;//总位数 
int w1=weishu;
while(w1--)
{
if(count==weishu)
zhongdian=number.size();
else
{
zhongdian=z;
}
int max=0;
//        cout<<"zhongdian="<<zhongdian<<endl;
for(int t1=i-count;t1<zhongdian;t1++)
{
//            cout<<"t1="<<t1<<endl;
if(number[t1]>max)
{
max=number[t1];
//                cout<<"max="<<max<<endl;
z=t1;
}
}
count++;
char c=max+'0';
s.push_back(c);
}
cout<<s;
return 0;
}


一直说我的输出和标准输出空格换行有问题,不知道怎么回事,求指点
编辑于 2020-05-24 18:09:40 回复(0)
#include<bits/stdc++.h>
using namespace std;
string remove(string s)
{
    if(s.size()==1) return "";
    for(int i=1;i<s.size();++i)
        if(s[i]>s[i-1])
            return s.substr(0,i-1)+s.substr(i);
    return s.substr(0,s.size()-1);
}
int main()
{
    string s;
    int k;
    while(cin>>s>>k)
    {
        while(k--)
        {
            s = remove(s);
        }
        cout<<s<<endl;
    }
    return 0;
}
发表于 2020-05-24 14:50:47 回复(0)
维护一个单调栈,栈顶元素比当前小的,出栈,计数减一。大的入栈。
最后若计数k1没用完,就去掉栈顶的k1个元素,
否则就将数组剩余的元素追加在栈里。
ss ,k= input().split()
k,nums= int(k),[]
for d in ss:
    nums.append(d)
stack,i  = [],0
while k>0 and i<len(nums):    
    if (stack and nums[i]<=stack[-1])&nbs***bsp;not stack:
        stack.append(nums[i])
        i+=1
    elif stack and nums[i]>stack[-1]:
        stack.pop()        
        k-=1
if k==0:
    stack+=nums[i:]
else:
    stack = stack[0:-k]
            
print(''.join(list(map(str,stack))))
    


编辑于 2020-04-26 16:36:19 回复(0)
单调队列实现
from collections import deque
import sys
nums, K = sys.stdin.readline().strip().split()
N = len(nums)
K = int(K)

res = ""
q = deque()
for i in range(N):
    while q and nums[i] > nums[q[-1]]:
        q.pop()
    q.append(i)
    if i >= K:
        res += nums[q[0]]
        q.popleft()
        if q and i-q[0] >=K:
            q.popleft()
print(res)


发表于 2020-03-31 21:19:01 回复(0)
#include<stdio.h>
#include<string.h>
int main()
{
int n=0;
int max=0;
char s[2000];
int k;
for(int i=1;i<=2000;i++)
{
scanf("%c",&s[i]);
if(s[i]!=' ')
{
n++;
}
else
{
break;
} 
}
scanf("%d",&k);
int temp1=0;//起始查找位置 
int temp2=0;//s[i]-'0'
int temp3=k+1; //结束查找位置 
for(int i=1;i<=n-k;i++)
{ 
max=0;
temp1=temp1+1;
for(int j=temp1;j<=temp3;j++)
{
temp2=s[j]-'0';
if(temp2>max)
{
max=temp2;//贪心
temp1=j; 
} 
}
temp3=temp3+1;
putchar(s[temp1]);
}
return 0;
} 


编辑于 2019-11-06 21:47:27 回复(0)
Java解法,可以完成功能,时间没来得及调试成功就结束了;
思路:获取字符串str和需要去掉的数字个数n,将字符串转换为字符数组;
            遍历n次每次将数组中值最小且角标最小的值修改为‘a’;
            由于数字的字符值都小于‘a’,所以在后续遍历一遍将所有值不是‘a’的字符存入新建的str的长度减n的字符数字中;
            
package studyJava.day0912;

import java.util.Scanner;

public class TestXiaomi {
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        //获取需要的字符串和整数N
        String string = in.next();
        int number = in.nextInt();

        String string2 = findMaxstr(string,number);


        System.out.println(string2);
    }

    /**
     * 传入字符串与数字,得到新的字符串
     * @param string
     * @param num
     * @return
     */
    public static String findMaxstr(String string, int num)
    {
        char[] str = string.toCharArray();
        for(int i=0; i<num; i++)
        {
            findMincharset(str);
        }
        char[] str2 = new char[str.length-num];
        int count=0;
        for(int x=0; x<str.length; x++)
        {
            if(str[x]!='a')
            {
                str2[count] = str[x];
                count++;
            }
        }
        String ss= new String(str2);
        return ss;
    }

    /**
     * 寻找最小的元素并将他替换成‘a’
     * @param str
     * @return
     */
    static void findMincharset(char[] str)
    {
        int min=0;
        for(int i=0; i<str.length-1; i++)
        {
            if(str[min]>str[i+1])
            {
                min = i+1;
            }
        }
        str[min] = 'a';
    }
}

该数组转换成字符串就是要求的字符串。
发表于 2019-09-12 17:00:55 回复(0)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>


char *search_biggest(char *string,int string_length,char *end);
int Get_Input(char *string,int *delect)
{
	int i=0;
	while(1)
	{
		string[i] =getchar();
		if(string[i]==' ')
		{
			break;
		}
		i++;
	}
	scanf("%d",delect);
	return i;
}


int main(void)
{
	char *front,*end,*string;
	int string_length,K,i;
	string = (char *)malloc(2000*sizeof(char));
	memset(string,0,2000*sizeof(char));
	string_length = Get_Input(string,&K);
	front = string;

	end   = string+string_length-1;
	for(i=0;i<=string_length-K-1;i++)
	{
		
		front = search_biggest(front,string_length-K-i,end);
	}

	free(string);

}

char *search_biggest(char *string,int string_length,char *end)
{
	char *front,*rear,*record;
	char temp; 
	front = string;
	rear  = front+string_length-1;
	temp = *front;
	record = front;
	while(1)
	{
		//printf("%d %d\n",front,record);
		if(*front>temp)
		{
			temp = *front;
			record = front;
		}
		if(rear == end)
		{
			break;	 
		} 
		front++;
		rear++;
	}
	printf("%c",temp); 
	return record+1;	
	 
}



















发表于 2019-09-03 22:21:54 回复(0)