Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
楼主: vbyou127

[已解决]VBA整数删数字后最小数

[复制链接]
发表于 2016-3-30 11:06 | 显示全部楼层    本楼为最佳答案   
本帖最后由 yorkchenshunan 于 2016-3-30 13:39 编辑

按照我的逻辑,先后删除的是3/4/5/6/8,过程如下
  1. Sub jisuan()
  2.     Dim ar, n%, m As Single, p%, r%, min1%, min2%, min3%, min%, br, cr, inp$
  3.         inp = Application.InputBox("说明:请输整数", "请输入任意整数", , , , , , 2)
  4.     If Not IsNumeric(inp) Then
  5.         MsgBox "输入有误"
  6.         Exit Sub
  7.     End If
  8.     ReDim ar(1 To Len(inp), 1 To 2) As Integer
  9.     For n = 1 To Len(inp)
  10.         ar(n, 1) = n
  11.         ar(n, 2) = Mid(inp, n, 1)
  12.     Next n
  13.     Do
  14.         m = Application.InputBox("说明:请输入1-" & Len(inp) - 1 & "之间的整数", "请输入删除数字个数", , , , , , 1)
  15.     Loop Until Int(m) = m And m >= 1 And m <= 16
  16.     min = 1
  17.     min3 = 1
  18.     ReDim br(1 To Len(inp) - m)
  19.     ReDim cr(1 To m)
  20.     For p = 1 To Len(inp) - m
  21.         min2 = 10
  22.         For r = min To p + m
  23.             If ar(r, 2) < min2 Then
  24.                 min1 = ar(r, 1)
  25.                 min2 = ar(r, 2)
  26.             End If
  27.         Next r
  28.         If min1 > min Then
  29.             For r = min To min1 - 1
  30.                 cr(min3) = ar(r, 2)
  31.                 min3 = min3 + 1
  32.             Next r
  33.         End If
  34.         min = min1 + 1
  35.         br(p) = min2
  36.     Next p
  37.     If min3 <= m Then
  38.         For p = 1 To m + 1 - min3
  39.             cr(m + 1 - p) = ar(UBound(ar) - p + 1, 2)
  40.         Next p
  41.     End If
  42.     MsgBox "先后删除数字:" & Join(cr, ",") & Chr(10) & "答案:" & Join(br, "")
  43.     End Sub
复制代码

点评

你的方法有bug。首位可能会出现0、也不能正确提取多位相同数。  发表于 2016-3-30 13:04

评分

参与人数 1 +9 收起 理由
vbyou127 + 9 来学习

查看全部评分

excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
回复

使用道具 举报

发表于 2016-3-30 12:03 | 显示全部楼层
  1. Sub tt()
  2.     Dim L, isfirst As Boolean
  3.     x = "13425638694"  '原数
  4.     jqs = 5       '截取数
  5.     msg = "原数:" & x & Chr(10) & "删除个数:" & jqs & Chr(10)
  6.     n = Len(x) - jqs   '要保留的个数
  7.     For k = n To 1 Step -1
  8.         If k = n Then isfirst = True Else isfirst = False
  9.         L = Len(x) - k + 1
  10.         y = getmin(Left(x, L), isfirst)
  11.         res = res & y
  12.         p = InStr(x, y)
  13.         jq = jq & Left(x, p - 1)
  14.         x = Mid(x, p + 1)
  15.     Next
  16.     MsgBox msg & "先后删除数字:" & jq & Chr(10) & "删除后最小:" & res
  17. End Sub
  18. Function getmin(x, isfirst As Boolean)      '得到字符串x中的最小数。如果是第一次取值,不含0。
  19.     If isfirst Then k = 1 Else k = 0
  20.     For i = k To 9
  21.         If InStr(x, i) Then Exit For
  22.     Next
  23.     getmin = i
  24. End Function
复制代码

评分

参与人数 2 +14 收起 理由
香川群子 + 5 赞一个
vbyou127 + 9 来学习

查看全部评分

回复

使用道具 举报

发表于 2016-3-30 12:32 | 显示全部楼层
这个题目有点意思。


已知m个数字串、需要删除n个数字,余下m-n个数字按原顺序排列得到的数值最小。

我想可以这么做:
1. 取前n+1个数位,找到其中不为零的最小值、如=1、然后剔除这个数之前的所有数字。
2. 继续增加1个数位,找到剩余数中最小值(可以=0),然后剔除这个数之前的所有数字。
3. 继续步骤2、直到剔除数的个数=n时终止。

评分

参与人数 1 +6 收起 理由
vbyou127 + 6 来学习

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2016-3-30 12:41 | 显示全部楼层
yorkchenshunan 发表于 2016-3-30 11:06
按照我的逻辑,先后删除的是3/4/5/6/8,过程如下

增加一个条件,删除后的最小数不能以0开头,会不会好难

点评

这个条件是合理的吧。  发表于 2016-3-30 13:17
回复

使用道具 举报

发表于 2016-3-30 12:59 | 显示全部楼层
算法的代码实现:
  1. Sub test() 'by kagawa
  2.    
  3.     s = InputBox("", "", "80317902254297017652") '输入数字串
  4.     m = Len(s) '得到数字串个数m
  5.     n = Val(InputBox("n=", "", 9)) '输入需要剔除数字的个数n
  6.    
  7.     ReDim a&(1 To m)
  8.     For i = 1 To n + 1 '填写前n+1个数
  9.         t = Mid(s, i, 1)
  10.         If t = "0" Then a(i) = 10 Else a(i) = t
  11.         '如果是0要改为10保护起来 不参加首位数挑选 【保留数首位不能=0】
  12.     Next
  13.     For i = n + 2 To m 'n+1以后的数先保护起来 不参加挑选
  14.         a(i) = 10
  15.     Next
  16.    
  17.     t = WorksheetFunction.min(a) '找到n+1中的最小值
  18.     j = WorksheetFunctin.Match(t, a, 0) '定位最早出现的这个最小值

  19.     For i = 1 To j - 1 '标记剔除数
  20.         a(i) = 11: k = k + 1 '标记剔除数、已剔除数统计k+1
  21.     Next
  22.     For i = j + 1 To n + 1
  23.         If a(i) = 10 Then a(i) = 0 '保护的0数值恢复 以便参加以后的挑选
  24.     Next
  25.     a(j) = 10 '第1个保留数标记
  26.    
  27.     r = n + 1 '从n+1位开始
  28.     Do While k < n '循环检查直到满足剔除个数k=n
  29.         r = r + 1
  30.         a(r) = Mid(s, r, 1) '第r位置写入这个数参与挑选
  31.         t = WorksheetFunction.min(a) '挑选最小值(可以=0)
  32.         j2 = WorksheetFunction.Match(t, a, 0) '最小值定位
  33.         For i = j + 1 To j2 - 1
  34.             a(i) = 11: k = k + 1 '标记剔除数、已剔除数统计k+1
  35.         Next
  36.         a(j2) = 10 '标记这个保留数
  37.         j = j2 '更新检查位置
  38.     Loop
  39.    
  40.     '以上完成、然后输出结果
  41.     s1 = s: s2 = s: s3 = ""
  42.     For i = 1 To m
  43.         If a(i) = 11 Then Mid(s2, i, 1) = "-" Else Mid(s1, i, 1) = "-": s3 = s3 & Mid(s, i, 1)
  44.     Next
  45.     MsgBox s & vbCr & s1 & vbCr & s2 & vbCr & s3
  46.     '显示为原数字串、剔除数、保留数、合并保留数
  47. End Sub
复制代码
例如:

9/20 (20位数字串中剔除9个数)

80317902254297017652
803-79---54-97------
---1--022--2--017652
10222017652

第1个0不能保留。
回复

使用道具 举报

发表于 2016-3-30 13:27 | 显示全部楼层
我的代码跟香川的思路完全一致。加上注释并改成手动输入。
  1. Sub tt()
  2.     Dim L, isfirst As Boolean
  3.     x = InputBox("请输入要截取的数字串", "", "80317902254297017652") '输入数字串
  4.     jqs = Val(InputBox("请输入的剔除数字的个数", "", 9)) '截取数(需要剔除数字的个数)
  5.     msg = "原数:" & x & Chr(10) & "删除个数:" & jqs & Chr(10)
  6.     n = Len(x) - jqs   '要保留的个数
  7.     For k = n To 1 Step -1    '要保留k位数
  8.         If k = n Then isfirst = True Else isfirst = False      '看看是不是第一位
  9.         L = Len(x) - k + 1       '去掉后面k-1位,取前半段
  10.         y = getmin(Left(x, L), isfirst)      '找到最小值,如果是第一次取值,不含0
  11.         res = res & y
  12.         p = InStr(x, y)      '最小值的位置p
  13.         jq = jq & Left(x, p - 1)     'p前各位即为删除的数字
  14.         x = Mid(x, p + 1)        'p后各位即为下一次截取的字符串
  15.     Next
  16.     MsgBox msg & "先后删除数字:" & jq & Chr(10) & "删除后最小:" & res
  17. End Sub
  18. Function getmin(x, isfirst As Boolean)      '得到字符串x中的最小数。如果是第一次取值,不含0。
  19.     If isfirst Then k = 1 Else k = 0
  20.     For i = k To 9
  21.         If InStr(x, i) Then Exit For
  22.     Next
  23.     getmin = i
  24. End Function
复制代码
回复

使用道具 举报

发表于 2016-3-30 13:45 | 显示全部楼层
vbyou127 发表于 2016-3-30 12:41
增加一个条件,删除后的最小数不能以0开头,会不会好难

简单。
  1.     Sub jisuan()
  2.     Dim ar, n%, m As Single, p%, r%, min1%, min2%, min3%, min%, br, cr, inp$
  3.         inp = Application.InputBox("说明:请输整数", "请输入任意整数", , , , , , 2)
  4.     If Not IsNumeric(inp) Then
  5.         MsgBox "输入有误"
  6.         Exit Sub
  7.     End If
  8.     ReDim ar(1 To Len(inp), 1 To 2) As Integer
  9.     For n = 1 To Len(inp)
  10.         ar(n, 1) = n
  11.         ar(n, 2) = Mid(inp, n, 1)
  12.     Next n
  13.     Do
  14.         m = Application.InputBox("说明:请输入1-" & Len(inp) - 1 & "之间的整数", "请输入删除数字个数", , , , , , 1)
  15.     Loop Until Int(m) = m And m >= 1 And m <= 16
  16.     min = 1
  17.     min3 = 1
  18.     ReDim br(1 To Len(inp) - m)
  19.     ReDim cr(1 To m)
  20.     For p = 1 To Len(inp) - m
  21.         min2 = 10
  22.         If p = 1 Then
  23.                 For r = min To p + m
  24.                 If ar(r, 2) < min2 And ar(r, 2) > 0 Then
  25.                     min1 = ar(r, 1)
  26.                     min2 = ar(r, 2)
  27.                 End If
  28.             Next r
  29.         Else
  30.             For r = min To p + m
  31.                 If ar(r, 2) < min2 Then
  32.                     min1 = ar(r, 1)
  33.                     min2 = ar(r, 2)
  34.                 End If
  35.             Next r
  36.         End If
  37.         If min1 > min Then
  38.             For r = min To min1 - 1
  39.                 cr(min3) = ar(r, 2)
  40.                 min3 = min3 + 1
  41.             Next r
  42.         End If
  43.         min = min1 + 1
  44.         br(p) = min2
  45.     Next p
  46.     If min3 <= m Then
  47.         For p = 1 To m + 1 - min3
  48.             cr(m + 1 - p) = ar(UBound(ar) - p + 1, 2)
  49.         Next p
  50.     End If
  51.     MsgBox "先后删除数字:" & Join(cr, ",") & Chr(10) & "答案:" & Join(br, "")
  52.     End Sub
复制代码
回复

使用道具 举报

发表于 2016-3-30 13:48 | 显示全部楼层
grf1973 发表于 2016-3-30 13:27
我的代码跟香川的思路完全一致。加上注释并改成手动输入。

你的代码,尾巴处理有问题,如输入12300111789,删除5位,显示不了删除8/9
回复

使用道具 举报

发表于 2016-3-30 13:51 | 显示全部楼层
香川群子 发表于 2016-3-30 12:59
算法的代码实现:例如:

9/20 (20位数字串中剔除9个数)

你的代码我10版的出错,j = WorksheetFunctin.Match(t, a, 0) 一句无法运行

回复

使用道具 举报

发表于 2016-3-30 13:56 | 显示全部楼层
本帖最后由 dsmch 于 2016-3-30 18:15 编辑
  1. Sub Macro1()
  2. x = "80317902254297017652" '文本型数值
  3. n = 11 '结果保留位数
  4. l=n
  5. t = Replace(Mid(x, 1, Len(x) - n + 1), "0", "")
  6. Do Until Len(zf) = l
  7.     p = 10
  8.     For i = 1 To Len(t)
  9.         s = Val(Mid(t, i, 1))
  10.         If s < p Then p = s
  11.     Next
  12.     n = n - 1
  13.     zf = zf & p
  14.     st = InStr(x, p)
  15.     x = Mid(x, st + 1)
  16.     t = Mid(x, 1, Len(x) - n + 1)
  17. Loop
  18. MsgBox zf'结果
  19. End Sub
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-5-5 08:39 , Processed in 0.295099 second(s), 14 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表